Отношение один-ко-многим получает дубликаты объектов, используя левое соединение - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть 2 класса в отношении «один ко многим» и запрос JPQL, который теперь работает, как я ожидал. Даже после прочтения некоторого поста об этом мне не кажется понятным.

@Entity
@Table(name = "context_entity")
public class ContextEntity {
    @Id
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY)
    @JoinColumn(name = "entity_id")
    private List<TypeSpecCharacteristicValue> metadata = null;
}

@Entity
@Table(name = "type_spec_characteristic_value")
public class TypeSpecCharacteristicValue {
    @Id
    private Long id;

    private String value;
}

Кстати Я вырезал только важную часть своего кода.

Если я запускаю следующий запрос, я получаю дубликаты объектов TypeSpecCharacteristicValue:

session.createQuery("select e.metadata from ContextEntity e left join e.metadata where e.id=:contextId")

Затем я проверяю оператор SQL, сгенерированный hibernate, что привело к следующему:

select metadata2_.id as id1_5_, metadata2_.value as value3_5_ from context_entity contextent0_ left outer join type_spec_characteristic_value metadata1_ on contextent0_.id=metadata1_.entity_id inner join type_spec_characteristic_value metadata2_ on contextent0_.id=metadata2_.entity_id where contextent0_.id=[some_context_id];

Почему hibernate генерирует второе соединение с таблицей type_spec characteristic_value? Должен ли я использовать различные?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Может быть, я попал в очень распространенное недопонимание JPA.

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

Несмотря на такое поведение, я обнаружил, что при следующей оптимизации в моем запросе второй JOIN исключается, и я не получаю повторяющихся результатов.

select m from ContextEntity e left join e.metadata m where e.id=:contextId

Теперь сгенерированный запрос приводит к:

select metadata1_.id as id1_5_, metadata1_.value as value3_5_ from context_entity contextent0_ left outer join type_spec_characteristic_value metadata1_ on contextent0_.id=metadata1_.entity_id where contextent0_.id=[some_context_id]

Я полагаю, что использование псевдонима в правой части соединения как-то указывает hibernate на непосредственный выбор объекта метаданных, и поэтому применяются некоторые оптимизации.

0 голосов
/ 03 сентября 2018

Я предполагаю, что второе (внутреннее) соединение неявно происходит из утверждения:

select e.metadata from ContextEntity e..

Используя оператор точки на объекте, вы вызываете связь между таблицами, поскольку вам также требуются все поля из другой таблицы.

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