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-2
和Book-10
之间的关联不变 -
BookStore-2
和Book-9
之间需要新建关联 -
BookStore-2
需要和Book-11
、Book-12
脱勾。
-
-
这很好理解,在删除父对象之前,首先需要对子对象进行脱勾处理。
@OnDissociate
只能用在基于外键映射的多对一关联上,比如
- Java
- Kotlin
@Entity
public interface Book {
@Null
@ManyToOne
@OnDissociate(DissociateAction.SET_NULL)
BookStore store();
...
}
@Entity
interface Book {
@ManyToOne
@OnDissociate(DissociateAction.SET_NULL)
val store: BookStore?
...
}
虽然子对象脱勾是由于一对多关联 (或逆向inverse一对一) 导致的 (即,父对象遗弃某些子对象,本例的一对多关联为BookStore.books
),但是脱勾模式的配置针对逆向的多对一关联 (本例为Book.store
),这样设计的目的是为了保持和数据库DDL外键的级联特性配置的相似性。
对于Jimmer而言,一对多关联一定是双向关联,知道某个一对多关联,一定知道与其互为镜像的多对一关联。所以,此设计没有任何问题。
脱钩模式
上面代码中OnDissociate
注解的参数,被称为脱钩模式
子对象脱勾操作有5种模式
模式 | 描述 |
---|---|
NONE (默认) | 视全局配置jimmer.default-dissociate-action-checking而定
|
LAX | 该选项只对伪外键有效 (请参见真假外键),否则,会被忽略,同CHECK。 即便存在子对象,也支持脱钩操作。即使发生父对象被删除的情况 (脱钩模式也被删除指令采用),也任由子对象的伪外键发生悬挂问题 (即便伪外键发生悬挂,查询系统也可以正常工作)。 |
CHECK | 如果存在子对象,则不支持脱勾操作,通过抛出异常阻止操作。 |
SET_NULL | 把被脱勾的子对象的外键设置为null。前提是子对象的多对一关联属性是nullable的;否则尝试此配置将会导致异常。 |
DELETE | 将被脱勾的子对象删除。 |
本文只介绍OnDissociate的配置,至于如何进一步使用,请参见保存指定/脱钩操作和删除指令。
动态覆盖
借助于实体中OnDissociate
注解的脱钩配置,叫做静态配置。
有的时候,不同的业务可能对脱钩操作有不同的要求,因此,脱钩配置可以在运行时被动态覆盖。
-
- Java
- Kotlin
sqlClient
.getEntities()
.saveCommand(book)
.setDissociateAction(BookProps.STORE, DissociateAction.SET_NULL)
.execute();sqlClient.save(book) {
.setDissociateAction(Book::store, DissociateAction.SET_NULL)
} -
- Java
- Kotlin
DeleteResult result = sqlClient
.getEntities()
.deleteCommand(BookStore.class, 1L)
.configure(it ->
it
.setDissociateAction(
BookProps.STORE,
DissociateAction.SET_NULL
)
)
.execute();val result = sqlClient
.entities
.delete(BookStore::class, 1L) {
setDissociateAction(
Book::store,
DissociateAction.SET_NULL
)
}