Hibernate Criteria join 查询一对多

Posted

技术标签:

【中文标题】Hibernate Criteria join 查询一对多【英文标题】:Hibernate Criteria join query one to many 【发布时间】:2013-07-16 02:04:18 【问题描述】:

我有一个 Cat 类和一个 Owner 类。一只猫有一个主人,但一个主人可以养很多只猫。我要查询的是获取所有拥有蓝眼睛猫的主人

class Cat 
    Owner owner; //referenced from Owner.id
    String eyeColor;


class Owner 
    List<Cat> catList;

我尝试了一些代码,但我真的不知道该怎么做。

Criteria criteria = getCurrentSession().createCriteria(cat.getClass(), "cat");
criteria.createAlias("cat.owner", "owner");    
criteria.add(Restrictions.eq("cat.eyeColor", "blue");

【问题讨论】:

关联是双向的吗?为什么不对这样的静态查询使用 HQL? @JBNizet 抱歉,但我别无选择,比如使用 HQL。 关联是双向的吗?为什么你没有选择?这就像木匠不允许使用锤子一样! @JBNizet 我编辑了。抱歉,这不是我的决定。 不能使用HQL,以防查询太复杂,最好写条件查询,还可以处理所有类型转换,比如将localDate类型转换为时区格式等。写HQL是一件痛苦的事尤其是当你在 where 子句的查询中有 100 个过滤器时,代码是一种编写长查询的托管方式,并且从长远来看易于维护。 【参考方案1】:

Criteria 只能选择投影或根实体。不是一些加入的实体。因此,某些查询无法使用 Criteria 来表达(这是使用 HQL 的另一个好理由,除了更好的可读性和简洁性之外)。

不过,这里并没有丢失所有内容,因为您的关联是双向的。所以你只需要等效的 HQL 查询

select distinct owner from Owner owner 
join owner.cats cat 
where cat.eyeColor = 'blue'

这是

Criteria c = session.createCriteria(Owner.class, "owner");
c.createAlias("owner.cats", "cat");
c.add(Restrictions.eq("cat.eyeColor", "blue");
c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

【讨论】:

在我的例子中,猫知道主人,但主人不知道他的猫。条件查询是什么样的? 正如我在回答中所说,AFAIK(除非他们在较新的版本中使其成为可能),使用标准是不可能的。使用 HQL,或使用 JPA2 标准 API。 这会在内存中进行“不同”操作。如果一个主人有一百万只蓝眼睛的猫,它会从数据库中获取它们,只是为了找到唯一的主人(这个例子可能不是提问者的真实案例,你不知道真正的基数)。请参阅我的答案,了解如何在数据库中完成。 它在内存中,但它可以解决问题,但我希望它可以在不使用 HQL 的情况下通过查询完成,但看起来 hibernate 不支持它【参考方案2】:

试试这个:

DetachedCriteria dc = DetachedCriteria.forClass(Cat.class, "inner")
    .add(Restrictions.eq("eyeColor", "blue"))
    .add(Restrictions.eqProperty("inner.owner", "outer.id"));

session.createCriteria(Owner.class, "outer")
    .add(Subqueries.exists(dc))
    .list();

这可以使用数据库中的索引,并且不会像@JB Nizet 的版本那样执行内存中的distinct 操作(请参阅我的评论)。索引将是:

CREATE INDEX idx_cat_owner_eyecolor ON Cat(fkOwner, eyeColor)

distinct 操作(在SQL 中或内存中)视为代码异味。它很少使用,许多新手程序员使用它来解决“为什么我有两次这一行”的问题。它几乎总是可以被重写,例如在这种情况下。必要时用例很少。

【讨论】:

在outer.pk中,pk是什么? 此查询不起作用并引发空指针异常。JBNizet 的查询运行良好。虽然我知道它不完全是一个查询是代码库不同而不是基于查询的不同但至少它有效。 @user1735921,你能分享一下 NPE 的堆栈跟踪吗?我相信你犯了其他错误。 outer.pk是主键,也许我应该用outer.id,我编辑了

以上是关于Hibernate Criteria join 查询一对多的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate Criteria Join 与 3 个表

(懒惰)使用 Hibernate Criteria API 的 LEFT OUTER JOIN

如何使用 Hibernate Criteria 连接两个具有 OneToMany 关系的表

hibernate 一对多 查询问题

Hibernate中Criteria的完整用法

Hibernate中Criteria的完整用法