我在更新我的实体时遇到问题。如您所见,我有三个实体。
LabelValueEntity
包含来自类 LabelSwitchEntity
的列表。
LabelSwitchEntity
包含来自类 SwitchCaseEntity
的列表。
正如您从我的 SQL 语句中看到的,字段 name
和 labelValueUUID
是唯一的。我的表中只允许该组合的一行。
当我用 LabelSwitchEntity
类的新列表更新父实体 (LabelValueEntity
) 时,我希望 Hibernate 删除旧列表本身并创建新实体。逐一更新 child 有点困难。这就是为什么我想直接删除所有相关的 child 。
当我更新 LabelValueEntity
并为其提供一个列表时,该列表包含一个具有唯一名称和 labelValueUUID
的 LabelSwitchEntity
(已经存在的实体DB) 组合我得到一个唯一的约束违反异常。好吧,这个错误很明显,因为正如我所说,该组合存在于数据库中。我在这里希望 Hibernate 足够聪明,可以在插入子对象之前将其删除。
我做错了什么?
@Entity
@Table(name = "label_value")
class LabelValueEntity(uuid: UUID? = null,
...
@OneToMany(
mappedBy = "labelValueUUID",
cascade = [CascadeType.ALL],
fetch = FetchType.EAGER,
orphanRemoval = true)
@Fetch(FetchMode.SUBSELECT)
val labelSwitchEntities: List<LabelSwitchEntity>? = emptyList()
) : BaseEntity(uuid)
@Entity
@Table(name = "label_switch")
class LabelSwitchEntity(uuid: UUID? = null,
@Column(name = "label_value_uuid", nullable = false)
val labelValueUUID: UUID,
@OneToMany(
mappedBy = "labelSwitchUUID",
cascade = [CascadeType.ALL],
fetch = FetchType.EAGER,
orphanRemoval = true
)
val switchCaseEntities: List<SwitchCaseEntity>,
@Column
val name: String,
...
) : BaseEntity(uuid)
@Entity
@Table(name = "switch_case")
class SwitchCaseEntity(uuid: UUID? = null,
...
@Column(name = "label_switch_uuid", nullable = false)
val labelSwitchUUID: UUID
) : BaseEntity(uuid)
CREATE TABLE label_switch
(
uuid UUID NOT NULL PRIMARY KEY,
label_value_uuid UUID REFERENCES label_value(uuid) ON DELETE CASCADE,
name CHARACTER VARYING (255) NOT NULL,
UNIQUE (label_value_uuid, name)
);
CREATE TABLE switch_case
(
uuid UUID NOT NULL PRIMARY KEY,
label_switch_uuid UUID NOT NULL REFERENCES label_switch(uuid) ON DELETE CASCADE
);
基础实体
@MappedSuperclass
abstract class BaseEntity(givenId: UUID? = null) : Persistable<UUID> {
@Id
@Column(name = "uuid", length = 16, unique = true, nullable = false)
private val uuid: UUID = givenId ?: UUID.randomUUID()
@Transient
private var persisted: Boolean = givenId != null
override fun getId(): UUID = uuid
@JsonIgnore
override fun isNew(): Boolean = !persisted
override fun hashCode(): Int = uuid.hashCode()
override fun equals(other: Any?): Boolean {
return when {
this === other -> true
other == null -> false
other !is BaseEntity -> false
else -> getId() == other.getId()
}
}
@PostPersist
@PostLoad
private fun setPersisted() {
persisted = true
}
}
最佳答案
这就是事务的来源。如果你在一个用 @Transactional
注释的方法中处理所有逻辑(无论是来自 javax
还是 spring
), hibernate 将在其范围内进行脏检查,但不进行验证。
换句话说——只要有一个事务,hibernate 就会跟踪对托管实体所做的更改,但它不会验证它——这是数据库的责任。在内存中处理时,不会检查实体的一致性。只需确保将一致的状态刷新到数据库(事务提交阶段的实体应该是一致的)。
当您的数据库允许时,其他选项也是可能的,例如在 postgres 中,您可以将约束标记为延迟。当约束被定义为deferred
时,它不会在打开的事务中检查,只会在提交时检查。
关于java - 一对多关系中的父实体更新不会删除 Spring Jpa Childs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62995940/