在一对多关系中指定子表的条件



我有两个具有一对多关系的实体对象(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 的主键而不是外键。

最新更新