Hibernate @ Где не работает с @NamedEntityGraph
Я пытаюсь использовать @Where
аннотация спящего режима на однонаправленном @ManyToMany
ассоциация при использовании @NamedEntityGraph
на родительском объекте (см. код ниже):
ПРИМЕЧАНИЕ. Я переименовал свои объекты в
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?