web-dev-qa-db-ja.com

Hibernate Criteria結合クエリ1対多

CatクラスとOwnerクラスがあります。猫の飼い主は1人ですが、飼い主は多くの猫を飼うことができます。クエリしたいのは猫の青い目を持つすべての所有者を取得するです。

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");
25
hellzone

基準では、投影またはルートエンティティのみを選択できます。結合されたエンティティではありません。したがって、一部のクエリはCriteriaで表現することが不可能です(読みやすさと簡潔さの向上に加えて、HQLを使用するもう1つの正当な理由です)。

ただし、関連付けは双方向であるため、ここですべてが失われるわけではありません。したがって、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);
43
JB Nizet

これを試して:

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またはメモリ内のいずれか)をコード臭と考えてください。これはめったに使用されず、多くの初心者プログラマーが「なぜこの行を2回持っているのか」という問題を解決するために使用します。ほとんどの場合、この場合のように書き換えることができます。必要な場合のユースケースはほとんどありません。

4
Oliv