Hibernate @ Где не работает с @NamedEntityGraph - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь использовать аннотацию гибернации @Where для однонаправленной ассоциации @ManyToMany при использовании @NamedEntityGraph на родительском объекте (см. Код ниже):

ПРИМЕЧАНИЕ: I ' Например, я переименовал мои сущности в Parent и Child. Кроме того, я использую Kotlin, который не должен отличаться от синтаксиса.

Класс сущности

@Entity
@Table(name = "Parent")
@NamedEntityGraph(
        name = "parent",
        attributeNodes = [
            NamedAttributeNode(value = "children")
        ]
)
class Parent(

        @Id
        @Column(name = "parent_id")
        var id: Long,

        @Column(name = "some_value")
        var someValue: Long,

        @ManyToMany(targetEntity = Child::class, fetch = FetchType.LAZY)
        @Where(clause = "state <> 'deleted'")
        @JoinTable(name = "Parent_Child",
                joinColumns = [JoinColumn(name = "parent_id")],
                inverseJoinColumns = [JoinColumn(name = "child_id")])
        var children: Set<Child>?

)

Репозиторий JPA

interface ParentRepository : JpaRepository<Parent, Long> {

    @EntityGraph(value = "parent")
    fun findBySomeValue(someValue: Long): List<Parent>

//    Tried this commented-out code, but that just added another condition to the 
//    final `WHERE` clause and not the `JOIN` condition.
//    @EntityGraph(value = "parent")
//    fun findBySomeValueAndChildrenStateNot(SomeValue: Long, state: String): List<Parent>
}

SQL Оператор Hibernate, созданный в консоли

Hibernate:
    select
        parent0_.parent_id as parent_1_1_0_,
        child2_.child_id as child_1_1_0_,
        parent0_.parent_id as some_v2_1_0_,
        child2_.state as state_2_1_0_ 
    from
        Parent parent0_ 
    left outer join
        Parent_Child children1_ 
            on parent0_.parent_id=children1_.parent_id 
    left outer join
        Child child2_ 
            on children1_.child_id=child2_.child_id 
            and (
                child2_.state <> 'deleted'
            ) 
    where
        parent0_.some_value=?
Hibernate: 
    select
        child0_.child_id as child_id1_15_0_,
        child0_.state as state_2_15_0_
    from
        Child child0_ 
    where
        child0_.child_id=?
Hibernate: 
    select
        child0_.child_id as child_id1_15_0_,
        child0_.state as state_2_15_0_
    from
        Child child0_ 
    where
        child0_.child_id=?

JSON Результат

[
  {
    "id": 1,
    "someValue": 1234,
    "children": [
      {
        "childId": 1,
        "state": "deleted"
      },
      {
        "childId": 2,
        "state": "active"
      }
    ]
  }
]

Проблемы

Есть пара проблем:

1) Как вы можете видеть для операторов SQL, Hibernate может использовать один запрос с объединениями для получения данных, но он также инициализирует больше SQL операторов выбора для каждого из дочерних связанных объектов. Hibernate должен использовать только первый выбор с соединениями.

2) Хотя первый оператор SQL SELECT содержит предложение state <> 'deleted' в операторе JOIN, результат JSON имеет детей с и active и deleted state. Это связано с двумя дополнительными операторами выбора.

Резюме / мысли

Сначала я подумал, что это связано с fetchType=LAZY и с тем, когда сущность Parent он был сериализован GSON, вызывал функцию «getter» и заставлял Hibernate извлекать данные, однако это не так. Я также попытался изменить его на fetchType=EAGER, но это ничего не изменило.

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

По сути, Как сказать Hibernate не запускать дополнительные операторы SELECT и просто использовать первый оператор с JOIN?

...