Родительский объект JPA mappedBy возвращал несколько раз ту же сумму, что и дочерние элементы

Я гуглил, но не нашел правильного ответа. Я использую JPA и Spring Data JPA. Я сопоставил родительскую таблицу с дочерней таблицей, где столбец соединения находится в дочерней таблице. Итак, в моей родительской таблице есть ссылка mappedBy, и я выполняю запрос JPA для родительского объекта, и вместо того, чтобы возвращать только 1, он возвращает столько, сколько есть дочерних объектов. Вот пример:

Мои таблицы очень упрощены

Parent

| ID |       COLUMN_A |
|----|----------------|
|  1 | Column A value |  

Child
| ID |   CHILD_COLUMN_A | PARENT_ID |
|----|------------------|-----------|
|  1 | Child column A 1 |         1 |
|  2 | Child column A 2 |         1 |
|  3 | Child column A 3 |         1 |

Я делаю собственный запрос, который возвращает то, что я хочу:
SELECT * FROM parent p INNER JOIN child c ON p.id = c.parent_id

| ID |   CHILD_COLUMN_A | PARENT_ID |
|----|------------------|-----------|
|  1 | Child column A 1 |         1 |
|  2 | Child column A 2 |         1 |
|  3 | Child column A 3 |         1 |

Мои сопоставления сущностей следующие:

@Entity
@Table(name = "parent")
public class Parent implements Serializable{
    ...
    @OneToMany(mappedBy="parent", cascade = CascadeType.PERSIST)
    List<child> children = new ArrayList<>();
        ...
}

@Entity
@Table(name = "child")
public class Child implements Serializable{
    ...
    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
        ....
}

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

@Query("SELECT p FROM Parent p INNER JOIN FETCH p.children c")
public Collection<Parent> getAll();

Таким образом, с приведенным выше запросом я получаю коллекцию с 3 Parent объектами вместо 1! И в каждом родительском объекте правильно 3 дочерних объекта, как и должно быть. Итак, вопрос в том, почему он возвращает Parent ту же сумму, что и Child? Я могу посмотреть на сгенерированный SQL, но просто увидеть его мне не очень поможет. Другая вещь, которую я могу добавить:

SELECT DISTINCT p FROM Parent p INNER JOIN FETCH p.children c

но опять же, он не оптимизирован, потому что сначала получает лишние объекты Parent с Child, а затем сужается до одного. Что, если бы у меня было 1000 объектов Child, тогда было бы создано 1000 объектов Parent, что было бы действительно ошеломляюще.

Я уверен, что это распространенная проблема, но я ничего не мог найти, был только конкретный ответ Hibernate на использование FetchType.SUBSELECT, но это не изменило результатов. Любая помощь приветствуется, спасибо.


person Skyzer    schedule 06.01.2014    source источник


Ответы (1)


Используйте ключевое слово DISTINCT, как вы описали, не беспокоясь, потому что это проблема уровня базы данных, чтобы сделать это эффективно. Кроме того, вы можете рассмотреть возможность удаления INNER JOIN с дочерними элементами, если у вас нет условий в запросе (которые вы не показали).

person Andrei I    schedule 06.01.2014
comment
Спасибо, я буду придерживаться этого и сравню операторы SQL, созданные с DISTINCT и без него. - person Skyzer; 06.01.2014