27

我有一个 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");
4

2 回答 2

48

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);
于 2013-07-17T14:03:13.917 回答
4

尝试这个:

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();

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

CREATE INDEX idx_cat_owner_eyecolor ON Cat(fkOwner, eyeColor)

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

于 2015-03-12T07:10:03.003 回答