寻找HQL构建器(休眠查询语言)

时间:2020-03-05 18:51:34  来源:igfitidea点击:

我正在寻找Java中HQL的构建器。我想摆脱像这样的事情:

StringBuilder builder = new StringBuilder()
    .append("select stock from ")
    .append( Stock.class.getName() )
    .append( " as stock where stock.id = ")
    .append( id );

我宁愿有这样的事情:

HqlBuilder builder = new HqlBuilder()
    .select( "stock" )
    .from( Stock.class.getName() ).as( "stock" )
    .where( "stock.id" ).equals( id );

我在Google上搜索了一下,但找不到。

我写了一个快速且愚蠢的" HqlBuilder",可以满足我现在的需求,但是我很想找到一个比我一个拥有更多用户和测试的人。

注意:我想能够做类似的事情,而我使用Criteria API却做不到:

select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.someValue = bonus.id

IE。从"奖金"表中选择属性" someValue"指向任何奖金的所有股票。

谢谢!

解决方案

回答

Criteria API不会为我们做到吗?它看起来几乎与要求完全一样。

回答

看来我们想使用Hibernate内置的Criteria查询API。要进行上述查询,它看起来像这样:

List<Stock> stocks = session.createCriteria(Stock.class)
    .add(Property.forName("id").eq(id))
    .list();

如果我们还没有访问Hibernate会话的权限,则可以使用'DetachedCriteria',如下所示:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class) 
    .add(Property.forName("id").eq(id));

如果要获取所有具有特定ID奖金的股票,则可以执行以下操作:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
     .createCriteria("Stock")
          .add(Property.forName("id").eq(id)));

有关更多信息,请查看Hibernate文档中的Criteria Queries

回答

@Sbastien Rocca-Serra

select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.bonus.id = bonus.id

那只是一个连接。当且仅当我们具有"股票"和"奖金"设置之间的映射并且"奖金"是"股票"的属性时,Hibernate才会自动执行此操作。 Criteria.list()将返回Stock对象,而我们只需调用stock.getBonus()。

请注意,如果我们想做类似的事情

select stock
from com.something.Stock as stock
where stock.bonus.value > 1000000

我们需要使用Criteria.createAlias()。就像

session.createCriteria(Stock.class).createAlias("bonus", "b")
   .add(Restrictions.gt("b.value", 1000000)).list()

回答

@Sbastien Rocca-Serra
现在,我们在具体的地方。通过Criteria API确实无法实现我们想要的那种连接,但是子查询应该完成相同的事情。首先,为奖金表创建一个" DetachedCriteria",然后对" someValue"使用" IN"运算符。

DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class);
List stocks = session.createCriteria(Stock.class)
    .add(Property.forName("someValue").in(bonuses)).list();

这相当于

select stock
from com.something.Stock as stock
where stock.someValue in (select bonus.id from com.something.Bonus as bonus)

唯一的缺点是,如果我们在someValue中引用了不同的表,并且ID在所有表中都不唯一。但是查询将遭受相同的缺陷。

回答

Criteria API并未提供HQL中所有可用的功能。例如,我们不能在同一列上进行多个联接。

我们为什么不使用命名查询?看起来更干净:

Person person = session.getNamedQuery("Person.findByName")
                             .setString(0, "Marcio")
                             .list();

回答

我为OMERO编写了GPL解决方案,我们可以轻松构建适合自己情况的解决方案。

  • 资料来源:QueryBuilder.java
  • 测试:QueryBuilderMockTest

用法:

QueryBuilder qb = new QueryBuilder();
qb.select("img");
qb.from("Image", "img");
qb.join("img.pixels", "pix", true, false);

// Can't join anymore after this
qb.where(); // First
qb.append("(");
qb.and("pt.details.creationTime > :time");
qb.param("time", new Date());
qb.append(")");
qb.and("img.id in (:ids)");
qb.paramList("ids", new HashSet());
qb.order("img.id", true);
qb.order("this.details.creationEvent.time", false);

它起着状态机" select-> from-> join-> where-> order"等的作用,并与可选参数保持同步。 Criteria API无法执行几个查询(请参阅HHH-879),因此最终编写此小类来包装StringBuilder更为简单。 (注意:有一个票证HHH-2407描述了一个将两个合并的Hibernate分支。在那之后,重新访问Criteria API可能很有意义)

回答

查看hibernate-generic-dao项目提供的搜索包。这是一个相当不错的HQL Builder实现。

回答

我知道这个线程已经很老了,但是我也在寻找一个HqlBuilder,我发现了这个"屏幕保护程序"项目
它不是Windows屏幕保护程序,而是
"实验室信息管理系统(LIMS),用于执行小分子和RNAi筛选的高通量筛选(HTS)设施。"

它包含一个看起来不错的HQLBuilder。
以下是可用方法的示例列表:

...
HqlBuilder select(String alias);
HqlBuilder select(String alias, String property);
HqlBuilder from(Class<?> entityClass, String alias);
HqlBuilder fromFetch(String joinAlias, String joinRelationship, String alias);
HqlBuilder where(String alias, String property, Operator operator, Object value);
HqlBuilder where(String alias, Operator operator, Object value);
HqlBuilder where(String alias1, Operator operator, String alias2);
HqlBuilder whereIn(String alias, String property, Set<?> values);
HqlBuilder whereIn(String alias, Set<?> values);
HqlBuilder where(Clause clause);
HqlBuilder orderBy(String alias, String property);
HqlBuilder orderBy(String alias, SortDirection sortDirection);
HqlBuilder orderBy(String alias, String property, SortDirection sortDirection);
String toHql();
...

回答

有关问题的类型安全方法,请考虑使用Querydsl。

示例查询变为

HQLQuery query = new HibernateQuery(session);
List<Stock> s = query.from(stock, bonus)
  .where(stock.someValue.eq(bonus.id))
  .list(stock);

Querydsl使用APT来生成JPA2之类的代码,并支持JPA / Hibernate,JDO,SQL和Java集合。

我是Querydsl的维护者,所以这个答案是有偏见的。