当前位置: 首页 > 知识库问答 >
问题:

在OneToMany关系中,父实体更新时不会删除Spring Jpa子实体

丁雅懿
2023-03-14

我的实体更新有问题。如你所见,我有三个实体。

LabelValueEntity包含类LabelSwitchEntity中的列表。
LabelSwitchEntity包含类SwitchCaseEntity中的列表。

从我的SQL语句中可以看到,字段nameLabelValueUId是唯一的。我的表中只允许该组合的一行。

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

当我更新LabelValueUentity并为其提供包含具有唯一名称的LabelSwitchEntityLabelValueUId(数据库中已存在的实体)组合的列表时,我会出现唯一约束冲突异常。这个错误很明显,因为正如我所说的,组合存在于DB中。在这里,我希望Hibernate足够聪明,可以在插入子文件之前删除它。

我做错了什么?

kotlin prettyprint-override">@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
    }
}

共有1个答案

淳于飞鸾
2023-03-14

这就是交易的来源地。如果处理用@transactional注释的方法(无论是Javax还是Spring)中的所有逻辑,那么hibernate将在其范围内进行脏检查,而不是验证。

换句话说--只要存在事务,hibernate就会跟踪对托管实体所做的更改,但它不会对其进行验证--这是数据库的责任。在内存中处理时,不检查实体的一致性。只需确保将一致状态刷新到数据库(事务提交阶段的实体应该是一致的)。

如果数据库允许的话,其他选项也是可能的,例如,在postgres中,您可以将约束标记为deferred。当约束被定义为deferred时,它不会在打开的事务中检查,只会在提交时检查。

 类似资料:
  • 删除父实体时,我还想删除关联的子实体(从数据库中)。我试图在删除时使用级联,如下所示,但我一定做错了什么。 当对父实体对象调用删除时,我收到错误消息:“该实体仍在数据库的其他地方引用”。我可以确认该实体在数据库的其他地方引用的唯一地方是在下面的两个表中(如果我手动从数据库中删除子行,对父实体对象的删除调用工作正常)。在过去的9个小时里,我一直在阅读实体对象并尝试不同的东西。我做错了什么? 这是我的

  • 我的实体。ValidationStep与documentDetail有一对一的关系,documentDetail与documentValidations有一个完全的关系 我的删除查询 父ValidationStep被删除,但是docDetail和documentValidations仍然在数据库中。

  • 我用的是SpringBoot和JPA Hibernate。 我有这些实体: 当我尝试删除父实体(Post)时,所有相关实体注释都保留在数据库中。为什么级联删除不起作用?

  • 我已经创建了纸张和Mcq问题之间的映射如下。 } 当我更新纸质实体时,它会删除所有MCQ。 SQL输出:

  • 我是Spring BootJPA的新手,正在努力找出多个实体之间的关系。 我有一个用户实体、一个产品实体和一个评论实体。一个用户有很多评论。一个产品有很多评论。评论有一个产品和一个用户。 目前,我正在为用户使用一对多的关系 我的问题: 如何在不删除产品实体和用户实体的情况下删除审阅实体? 我应该使用哪种级联类型? 用户实体: 产品实体: 审查实体: 用户控制器: 用户服务: 简单运行: 我认为我不

  • 在使用Hibernate删除与子实体具有关系的JPA实体时,我遇到了一个问题,但是在使用EclipseLink而不是Hibernate作为JPA提供程序时,相同的代码可以正常工作。父实体上的批注是 当使用Hibernate时,它尝试将子实体上的join列设置为null,但由于该列不允许null而失败。使用EclipseLink时,它首先删除子实体,然后删除父实体,这是所需的行为。 我的问题是: 为