java - 一对多关系中的父实体更新不会删除 Spring Jpa Childs

标签 java spring kotlin jpa spring-data-jpa

我在更新我的实体时遇到问题。如您所见,我有三个实体。

LabelValueEntity 包含来自类 LabelSwitchEntity 的列表。
LabelSwitchEntity 包含来自类 SwitchCaseEntity 的列表。

正如您从我的 SQL 语句中看到的,字段 namelabelValueUUID 是唯一的。我的表中只允许该组合的一行。

当我用 LabelSwitchEntity 类的新列表更新父实体 (LabelValueEntity) 时,我希望 Hibernate 删除旧列表本身并创建新实体。逐一更新 child 有点困难。这就是为什么我想直接删除所有相关的 child 。

当我更新 LabelValueEntity 并为其提供一个列表时,该列表包含一个具有唯一名称和 labelValueUUIDLabelSwitchEntity(已经存在的实体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/

相关文章:

java - Spring boot集成mybstis如何通过向导初始化数据库

spring - 如何在 AWS Lambda 函数中从 AWS API Gateway URI 访问请求和路径变量

generics - 我对同一个类有两个 Kotlin 扩展方法,但是具有不同的通用签名并且编译器会提示

java - 在 Java 中的字符串的字母之间添加 x 个空格?

java - UDP Java 数据报

java - Ajax 请求始终映射到根

kotlin - 使用 RxJava 构建 MVI 循环 : how to replace BehaviorSubject with scan()

java - Android开发中的Button和Androidx.appcompat.widget.AppCompatButton有什么区别?

java - fileinputstream 中 read 方法中使用的字节数据类型

javascript - 用户界面中的 Spring boot AJAX POST 请求和 knockout.js 调试错误