Задание критериев для дочерней таблицы в отношениях один ко многим

У меня есть два объекта сущности (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", но когда я пытаюсь получить доступ к "B" через "A" a.getB() два критерия, которые я указал для abJoined не применяются, и я получаю все экземпляры "B", которые соединены с "A". Есть ли что-то еще, что мне нужно сделать, чтобы применить эти критерии? Если критерии не могут быть применены, есть ли рекомендуемый метод для удаления соответствующих экземпляров "B" из набора результатов?

Я могу предоставить больше кода или других деталей, если это необходимо.

2 ответа

Решение

Запрос используется для выбора того, какие объекты должны быть возвращены запросом. Но объекты A никогда не будут частичными объектами, содержащими только подмножество их B. Они всегда будут полными экземплярами A, отражающими состояние того, что A находится в базе данных, и с каким B это связано.

Кстати, даже если бы это было возможно (это не так, и явно запрещено спецификацией JPA), ваш запрос должен был бы по крайней мере также загрузить B, используя выборочное соединение. В противном случае запрос возвращает только состояние A, а связанные B загружаются лениво.

Но в JPA для отношения @OneToMany Query запускается первым по мастеру со всеми критериями и выбирает только основные записи. Позже по отдельности выполняется запрос, НО, НО, НО...... критерии таблицы B будут содержать не все условия, а только одно условие, т.е. только первичный ключ VALUE основных записей, извлеченных, т. Е. Только с одним условием "b. A_id = [primarykeyfetched from master] "

SOLUTION - это просто Make a Independent класс, в котором нам нужны поля отношения @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 вместо внешнего ключа.

Другие вопросы по тегам