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

时间:2008-09-11 15:12:52

标签: java hibernate 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

即。从奖金表中选择财产someValue指向任何奖金的所有股票。

谢谢!

11 个答案:

答案 0 :(得分:6)

Criteria API不是为你做的吗?它看起来几乎就像你要求的那样。

答案 1 :(得分:6)

对于问题的类型安全方法,请考虑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的维护者,所以这个答案有偏见。

答案 2 :(得分:5)

对于另一个类型安全的查询dsl,我建议http://www.torpedoquery.org。该库仍然很年轻,但它通过直接使用您的实体类提供类型安全。这意味着在重构或重新设计之前查询不再适用时,早期的编译器错误。

我还为您提供了一个示例。我想从你的帖子中你试图做一个子查询限制,所以我基于这个例子:

import static org.torpedoquery.jpa.Torpedo.*;

Bonus bonus = from(Bonus.class);
Query subQuery = select(bonus.getId());

Stock stock = from(Stock.class);
where(stock.getSomeValue()).in(subQuery);

List<Stock> stocks = select(stock).list(entityManager);

答案 3 :(得分:4)

看起来您想要使用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

答案 4 :(得分:4)

@ Sébastien Rocca-Serra
现在我们正在变得具体。您尝试做的联接实际上并不是通过Criteria API实现的,但是子查询应该完成同样的事情。首先,为奖励表创建DetachedCriteria,然后使用IN运算符someValue

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在所有表中都不是唯一的。但是你的查询会遇到同样的缺陷。

答案 5 :(得分:2)

@ Sébastien Rocca-Serra

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

那只是一个加入。 Hibernate会自动执行此操作,当且仅当您在StockBonus设置之间建立映射并且bonusStock的属性时才会自动执行此操作。 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()

答案 6 :(得分:2)

Criteria API不提供HQL中可用的所有功能。例如,您不能在同一列上执行多个连接。

为什么不使用 NAMED QUERIES ?看起来更干净:

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

答案 7 :(得分:2)

我为OMERO编写了一个GPL解决方案,您可以根据自己的情况轻松构建该解决方案。

用法:

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-&gt; from-&gt; join-&gt; where-&gt; order”等,并与可选参数保持同步。 Criteria API无法执行多个查询(请参阅HHH-879),因此最后编写此小类以包装StringBuilder更简单。 (注意:有一个票据HHH-2407描述了一个Hibernate分支,它应该统一两者。之后,重新访问Criteria API可能是有意义的)

答案 8 :(得分:2)

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

答案 9 :(得分:2)

我知道这个帖子很老了,但我也在寻找一个HqlBuilder而且我找到了这个"screensaver" project
它不是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();
...

答案 10 :(得分:0)

现在也可以使用标准JPA Type Safe查询,标准较低但也很好Object Query

示例:

JPA Type Safe

EntityManager em = ...
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Stock> c = qb.createQuery(Stock.class);
Root<Stock> = c.from(Stock.class);
Predicate condition = qb.eq(p.get(Stock_.id), id);
c.where(condition);
TypedQuery<Stock> q = em.createQuery(c); 
List<Stock> result = q.getResultList();

对象查询

EntityManager em = ...
ObjectQuery<Stock> query = new GenericObjectQuery<Stock>(Stock.class);
Stock toSearch = query.target();
query.eq(toSearch.getId(),id);
List<Stock> res = (List<Stock>)JPAObjectQuery.execute(query, em);