我有两个具有一对多关系的实体对象(A 和 B)。我正在使用 JPA(Hibernate)来联接这些表并查询它们以获取特定结果集,但在获取结果时,我为子表 (B) 指定的条件不适用。这就是我定义查询的方式:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<A> query = builder.createQuery(A.class);
Root<A> a = query.from(A.class);
Join<A, B> abJoined = a.join(A_.b);
query.distinct(true)
.where(builder.and(
builder.equal(a.get(A_.id), id),
builder.equal(a.get(A_.active), 1),
builder.equal(a.get(A_.location), 1011),
builder.equal(a.get(A_.status), "Pending"),
builder.equal(abJoined.get(B_.status), "Not Moved"),
builder.greaterThan(abJoined.get(B_.detailId), 0)
));
当我调用entityManager.createQuery(query).getResultList();
时,我得到了实体"A"的一个实例,但是当我尝试通过"A"访问"B"时a.getB()
我为abJoined
指定的两个条件不适用,我得到了所有连接到"A"的"B"实例。我还需要做些什么来应用这些标准吗?如果无法应用条件,是否有推荐的方法从结果集中删除相应的"B"实例?
如有必要,我可以提供更多代码或其他详细信息。
查询用于选择查询必须返回哪些 A 实体。但 A 实体永远不会是仅包含其 B 子集的部分实体。它们将始终是 A 的完整实例,反映数据库中 A 的状态,以及此 A 与哪个 B 相关。
顺便说一句,即使这是可能的(它不是,并且被 JPA 规范明确禁止),您的查询至少也必须使用 fetch 连接加载 B。否则,查询仅返回 A 的状态,并延迟加载链接的 B。
但在 JPA 中,对于@OneToMany关系,查询首先在主节点上触发,其中包含所有条件,并且只获取主记录。稍后单独触发查询,但是但是......B 表标准不会包含所有条件,而只包含一个条件,即仅包含获取的主记录的主键值,即只有一个条件"b.A_id=[从主文件获取的主键]"
解决方案很简单创建一个独立类,其中我们需要@OneToMany关系字段
步骤 1
public class AB {
private A a;
private B b; //@OneToMany with A in the Entity class definitions
public AB(){}
public AB(A a, B b){ ///Very Important to have this constructor
this.a=a;
this.b=b;
}
getter setter....
}
步骤 2
CriteriaQuery<AB> q = criteriaBuilder.createQuery(AB.class);
Root<A> fromA = criteriaQuery.from(A.class);
List<Predicate> predicates = new ArrayList<Predicate>();
Join<A,B> fromB = fromA.join("b", JoinType.INNER);/*"b",fieldName of B in entity Class A*/
criteriaQuery.select(criteriaBuilder.construct(AB.class,A,B));//looks AB's 2 param constr.
predicates.add(criteriaBuilder.equal(fromA.get("name"), filter.getName()));
predicates.add(criteriaBuilder.equal(fromB.get("salary"), filter.getSalary()));
..........
List<AB> ABDataList = typedQuery.getResultList();
for(AB eachABData :ABDataList){
....put in ur objects
obj.setXXX(eachABData.getA().getXXX());
obj.setYYY(eachABData.getB().getYYY());
}
这将给出将所有条件应用于主表 A 的所有结果,并比较表 B 的主键而不是外键。