Как удалить несвязанные связанные сущности при сохранении нового экземпляра родительской сущности? - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь использовать Kotlin-y неизменности свойств в существующей системе, которая использует Hibernate.Структура сущности:

  • Родительский
    • Различные свойства
    • Список дочерних элементов
      • Дочерние свойства
      • Список внуков

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

Чтобы сохранить их как val s, нам нужно создать новые экземплярыParent, Child и GrandChild, когда мы хотим обновить сущность Parent и сохранить ее.Однако это вызывает исключение, сообщающее, что в сеансе присутствуют несколько экземпляров Parent с одним и тем же идентификатором.

Это можно обойти, либо вызвав clear(), чтобы удалить все объекты из кэша сеанса,или вызывая merge() для слияния нового объекта с существующей кэшированной сущностью.

Однако, несмотря на все каскады и orphanRemovals, это не удаляет дочерние элементы, которые больше не связаны с Parentили GrandChilds, которые больше не связаны с Child.Поэтому при извлечении Parent все еще возвращаются Childs и GrandChilds, которые должны были быть удалены.

Например, Parent 99 с Childs 1,2 и 3, новый экземпляр Parent A создается в коде Kotlin с использованием

val updatedParent = Parent(99, "NewName", "NewDesc")
val updatedChildren = listOf(
   Child(1, "NewChildName", "NewChildDesc", updatedParent),
   Child(2, "NewChild2Name", "NewChild2Desc", updatedParent)
)
updatedParent.addAll(updatedChildren)

(Это необходимо, потому что Hibernate нужен полный экземпляр связанного объекта для создания взаимосвязи, к сожалению)

Этот должен удалить Child # 3 при сохранении.В действительности, новые значения для Parent и 2 обновленных Childs корректно обновляются, но Child # 3 не удаляется.

2 "обходных пути", которые мне удалось найти, это либо

1) Вручную определите, какие существующие дочерние элементы отсутствуют в обновленном родительском объекте, и удалите их либо напрямую через HQL, либо с помощью orphanRemoval=true, чтобы удалить его из списка children не обновленного родительского объекта.

2) Откажитесь от неизменности Kotlin для этих свойств и внесите изменения в кешированный объект Hibernate напрямую.

Вариант 1 работает для прямых потомков Parent, но по мере углубления в внуков он становится громоздким исложно.

Вариант 2, очевидно, нежелателен, поскольку он сводит на нет некоторые преимущества использования Kotlin.

Каков наилучший способ поддержания неизменности в объектах домена Kotlin Hibernate при возможности обновления существующихлица?

@Entity
@Table("parent")
class Parent(
   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   val id: Long = 0,
   val name,
   val description,
    @OneToMany(
            cascade = [CascadeType.ALL],
            mappedBy = "parent",
            fetch = FetchType.EAGER,
            targetEntity = Child::class,
            orphanRemoval = true
    )
    @Fetch(FetchMode.SELECT)
    val children: MutableList<Child> = mutableListOf()
)

@Entity
@Table("child")
class Child(
   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   val id: Long = 0,
   val childName,
   val childDescription,
   @ManyToOne(optional = false, fetch = FetchType.LAZY, targetEntity = Parent::class)
    @JoinColumn(name = "parentId",
            foreignKey = ForeignKey(name = "FK_CHILD_PARENT"),
            referencedColumnName = "id"
    )
    val parent: Parent,
    @OneToMany(
            cascade = [CascadeType.ALL],
            mappedBy = "child",
            fetch = FetchType.EAGER,
            targetEntity = GrandChild::class,
            orphanRemoval = true
    )
    @Fetch(FetchMode.SELECT)
    val grandchildren: MutableList<GrandChild> = mutableListOf()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...