9

我正在寻找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指向任何红利的所有股票。

谢谢!

4

11 回答 11

9

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

于 2010-01-11T21:07:01.727 回答
7

Criteria API不是为您做的吗?它看起来几乎与您要求的完全一样。

于 2008-09-11T15:20:11.380 回答
5

@ Sébastien Rocca-Serra
现在我们要到具体的地方了。您尝试执行的那种连接实际上无法通过 Criteria API 进行,但子查询应该完成同样的事情。首先为红利表创建 a DetachedCriteria,然后使用IN运算符 for 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 在所有表中不是唯一的。但是您的查询将遭受同样的缺陷。

于 2008-09-11T17:02:48.123 回答
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);
于 2011-12-04T02:21:35.400 回答
4

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

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

如果您还没有访问 Hibernate Session 的权限,您可以像这样使用“DetachedCriteria”:

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

如果您想获取所有具有特定 ID 的 Bonus 股票,您可以执行以下操作:

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

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

于 2008-09-11T15:27:56.527 回答
2

@塞巴斯蒂安·罗卡-塞拉

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

那只是一个连接。Hibernate 会自动执行此操作,当且仅当您拥有StockBonussetup 之间的映射并且 ifbonusStock. 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()
于 2008-09-11T15:42:11.360 回答
2

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

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

Person person = session.getNamedQuery("Person.findByName")
                             .setString(0, "Marcio")
                             .list();
于 2008-09-11T17:32:59.253 回答
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->from->join->where->order”等,并跟上可选参数。有几个 Criteria API 无法执行的查询(参见HHH-879),所以最后编写这个小类来包装 StringBuilder 会更简单。(注意:有一个票据HHH-2407描述了一个应该统一两者的 Hibernate 分支。在那之后,重新访问 Criteria API 可能是有意义的)

于 2009-02-25T15:15:04.230 回答
2

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

于 2009-12-02T20:10:15.523 回答
2

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

它包含一个看起来相当不错的 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();
...
于 2009-12-10T10:38:12.620 回答
1

现在还可以使用标准的JPA 类型安全查询和一个不太标准但也很好的对象查询

例子:

JPA 类型安全

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);
于 2013-07-09T10:20:24.467 回答