JPA2 Criteria queries on entity hierarchy

三世轮回 提交于 2019-11-29 07:32:06

You need to base your query on entity2.details. Since the criteria API is type-safe, it catches that entity1 has no field named "details"

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery q = builder.createQuery();
Root r = q.from(Entity2.class);    // Must use subclass as root
q.select(r);
q.where(builder.gt(r.join("details", JoinType.LEFT).get("quantity"), 1));

Since Entity2 extends Entity1, you can cast your results as the parent type safely. For example:

CriteriaQuery<Entity1> q = builder.createQuery(Entity1.class);
Root r = q.from(Entity2.class);    // Must use subclass as root

will return a list of Entity1

CriteriaQuery<Entity2> q = builder.createQuery(Entity2.class);
Root r = q.from(Entity2.class);    // Must use subclass as root

will return a list of Entity2

EDIT:

I think I misunderstood the goal here. If you want all Entity1 UNLESS they are Entity2 with details.quantity <= 1, you need to do more.

You can't use a left join from Entity1Detail to Entity1, because that is not strictly type safe. Instead, you need to join Entity2 to Entity1Detail somehow. Probably the best tool to use here is a correlated subquery.

CriteriaQuery<Entity1> q = builder.createQuery(Entity1.class);
Root<Entity1> ent1 = q.from(Entity1.class);

SubQuery<Entity2> subq = q.subquery(Entity2.class);
Root<Entity2> ent2 = subq.from(Entity2.class);
Path<Integer> quantity = ent2.join("details", JoinType.LEFT).get("quantity");
Predicate lessThan = builder.lte(quantity,1);
Predicate correlatedSubqJoin = cb.equal(ent1,ent2)
subq.where(lessThan, correlatedSubqJoin);

q.select(ent1);
q.where(builder.exists(subq).not());

The criteria API does not know that you are single table inheritance, so you have to write your queries for all inheritance strategies, including a Joined inheritance strategy.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!