跳到主要内容

OnDissociate

概念

@org.babyfish.jimmer.sql.OnDissociate用于和修改篇/保存指令修改篇/删除指令配合

  • 修改篇/保存指令

    数据库已有数据结构用户期望保存的数据结构
    +-BookStore(id=2)
    |
    +-----Book(id=10)
    |
    +-----Book(id=11)
    |
    \-----Book(id=12)


    +-BookStore(id=2)
    |
    +-----Book(id=10)
    |
    |
    |
    |
    |
    \-----Book(id=9)

    这表示

    • BookStore-2Book-10之间的关联不变

    • BookStore-2Book-9之间需要新建关联

    • BookStore-2需要和Book-11Book-12脱勾。

  • 修改篇/删除指令

    这很好理解,在删除父对象之前,首先需要对子对象进行脱勾处理。

@OnDissociate只能用在基于外键映射的多对一关联上,比如

Book.java
@Entity
public interface Book {

@Null
@ManyToOne
@OnDissociate(DissociateAction.SET_NULL)
BookStore store();
...
}
信息

虽然子对象脱勾是由于一对多关联 (或逆向inverse一对一) 导致的 (即,父对象遗弃某些子对象,本例的一对多关联为BookStore.books),但是脱勾模式的配置针对逆向的多对一关联 (本例为Book.store),这样设计的目的是为了保持和数据库DDL外键的级联特性配置的相似性。

对于Jimmr而言,一对多关联一定是双向关联,知道某个一对多关联,一定知道与其互为镜像的多对一关联。所以,此设计没有任何问题。

脱钩模式

上面代码中OnDissociate注解的参数,被称为脱钩模式

子对象脱勾操作有5种模式

模式描述

NONE

(默认)

视全局配置jimmer.default-dissociate-action-checking而定

LAX

该选项只对伪外键有效 (请参见真假外键),否则,会被忽略,同CHECK。

即便存在子对象,也支持脱钩操作。即使发生父对象被删除的情况 (脱钩模式也被删除指令采用),也任由子对象的伪外键发生悬挂问题 (即便伪外键发生悬挂,查询系统也可以正常工作)

CHECK如果存在子对象,则不支持脱勾操作,通过抛出异常阻止操作。
SET_NULL把被脱勾的子对象的外键设置为null。前提是子对象的多对一关联属性是nullable的;否则尝试此配置将会导致异常。
DELETE将被脱勾的子对象删除。

本文只介绍OnDissociate的配置,至于如何进一步使用,请参见保存指定/脱钩操作删除指令

动态覆盖

借助于实体中OnDissociate注解的脱钩配置,叫做静态配置。

有的时候,不同的业务可能对脱钩操作有不同的要求,因此,脱钩配置可以在运行时被动态覆盖。

  • 修改篇/保存指令

    sqlClient
    .getEntities()
    .saveCommand(book)
    .setDissociateAction(BookProps.STORE, DissociateAction.SET_NULL)
    .execute();
  • 修改篇/删除指令

    DeleteResult result = sqlClient
    .getEntities()
    .deleteCommand(BookStore.class, 1L)
    .configure(it ->
    it
    .setDissociateAction(
    BookProps.STORE,
    DissociateAction.SET_NULL
    )
    )
    .execute();