Specifying criteria for child table in One To Many Relationship

一笑奈何 提交于 2019-12-13 17:00:50

问题


I have two entity objects (A and B) that have a One-To-Many relationship. I am using JPA (Hibernate) to join these tables and query them for a specific result set, but the criteria I specify for the child table (B) are not applied when fetching my results. This is how I have defined the query:

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

When I call entityManager.createQuery(query).getResultList(); I get one instance of entity 'A', but when I try to access 'B' through 'A' a.getB() the two criteria that I had specified for abJoined are not applied and I get all instances of 'B' that are joined to 'A'. Is there something more I need to do to get these criteria applied? If the criteria cannot be applied, is there a recommended method for removing the corresponding instances of 'B' from the result set?

I can provide more code or other details if necessary.


回答1:


The query is used to select which A entities must be returned by the query. But the A entities will never be partial entities containing only a subset of their Bs. They will always be complete instances of A, reflecting the state of what A is in the database, and which B this A is related to.

BTW, even if this was possible (it's not, and explicitely forbidden by the JPA spec), your query would at least have to load the Bs as well, using a fetch join. Otherwise only the state of A is returned by the query, and the linked Bs are loaded lazily.




回答2:


But in JPA, for a @OneToMany relationship, Query is fired first on the master, with all the Criteria and fetches just master records. Later Individually the query is fired, BUT BUT BUT......the B table criteria will not contain all the conditions, but only one condition i.e. just the primary key VALUE of master records fetched in i.e just with one condition "b.A_id=[primarykeyfetched from master]"

SOLUTION is simple Make an Independent class, in which we require the fields of @OneToMany relationship

STEP 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....

}

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

This will give all the results applying all the criteria to master table A, and comparing the primary key of Table B instead of foreign key.



来源:https://stackoverflow.com/questions/21030110/specifying-criteria-for-child-table-in-one-to-many-relationship

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