Я пытаюсь использовать аннотацию гибернации @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?