Критерии jpa запрашивают повторяющиеся значения в выбранном списке - PullRequest
4 голосов
/ 02 апреля 2012

Я наблюдаю то, что я считаю неожиданным поведением в JPA 2 при получении атрибута списка с запросом критерия.

Мой запрос выглядит следующим образом (выдержка из него):

CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<MainObject> c = b.createQuery(MainObject.class);
Root<MainObject> root = c.from(MainObject.class);
Join<MainObject, FirstFetch> firstFetch = (Join<MainObject, FirstFetch>) root.fetch(MainObject_.firstFetch);
firstFetch.fetch(FirstFetch_.secondFetch); //secondFetch is a list
c.select(root).distinct(true);

(Допустим, я выбираю список как свойство свойства объекта.)

Дело в том, что когда запрос возвращает несколько результатов, значения secondFetch дублируются столько раз, сколько строк возвращается. Каждый firstFetch должен иметь только один secondFetch , но вместо него есть n . Единственная особенность, которую я вижу в этом случае, состоит в том, что все MainObjects случайно имеют один и тот же экземпляр FirstFetch. Таким образом, я предполагаю, что соединение пересекается, что является нормальным, но затем JPA не может назначить свой объект secondFetch каждому из firstFetchs .

Отображения не должны быть слишком особенными, более или менее такие

@Entity
@Table(name="mainobject")
public class MainObject{
   //...
   private FirstFetch firstFetch;

   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="mainObject_column")
   public FirstFetch getFirstFetch() {
    return firstFetch;
   }
}

и

@Entity
@Table(name="firstFetch")
public class FirstFetch{
   //...
   private List<SecondFetch> secondFetch;

   @OneToMany(mappedBy="secondFetch")
   public List<SecondFetch> getSecondFetch() {
      return secondFetch;
   }
}

и наконец

@Entity
@Table(name="secondFetch")
public class SecondFetch {
    //....
    private FirstFetch firstFetch; //bidirectional

     @ManyToOne
     @JoinColumn(name="column")
     public FirstFetch getFirstFetch() {
        return firstFetch;
     }
}

Я искал какое-то отдельное предложение, которое можно применить к извлечению, но его нет (в любом случае это был бы «патч» ...)

Если я изменюсь

List<SecondFetch>

для

Set<SecondFetch>

я получу ожидаемый результат благодаря наборам Keys , поэтому я чувствую, что это некое поведение в списках JPA.

Хотя я не эксперт, поэтому я вполне мог бы ошибиться в отображениях или запросах. Любая обратная связь приветствуется, чтобы помочь в этом разобраться. Спасибо.

1 Ответ

3 голосов
/ 19 апреля 2012

У меня была точно такая же проблема, хотя я использовал API критериев JPA для выполнения запроса.

После некоторых исследований я нашел решение, которое вы уже упомянули (но не было доступно, поскольку вы не используете API критериев): использование distinct.

С критериями JPA это будет выглядеть так:

CriteriaQuery<FirstFetch> query = cb.createQuery(FirstFetch.class);
Root<AbschnittC> root = query.from(FirstFetch.class);
root.fetch(FirstFetch_.secondFetch, JoinType.LEFT);
query.distinct(true); 

Без использования query.distinct(true); набор результатов умножается на количество объектов в списке secondFetch.

В Hibernate есть что-то вроде DISTINCT_ROOT_ENTITY, которое звучит более адекватно, чем просто установка отдельного запроса. Но я больше не исследовал это. Я также использую Hibernate в качестве поставщика JPA. Может быть, установка query отличного в JPA заканчивается тем же кодом, что и Hibernates DISTINCT_ROOT_ENTITY?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...