寻找HQL构建器(休眠查询语言)
我正在寻找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的维护者,所以这个答案是有偏见的。