OnDissociate
Concepts
@org.babyfish.jimmer.sql.OnDissociate
is used together with Modification/Save Command and Modification/Delete Command
-
Existing data structure in database Data structure expected to be saved by user +-BookStore(id=2)
|
+-----Book(id=10)
|
+-----Book(id=11)
|
\-----Book(id=12)+-BookStore(id=2)
|
+-----Book(id=10)
|
|
|
|
|
\-----Book(id=9)This means:
-
The association between
BookStore-2
andBook-10
remains unchanged -
The association between
BookStore-2
andBook-9
needs to be created -
BookStore-2
needs to be disassociated fromBook-11
andBook-12
.
-
-
This is easy to understand. Child objects need to be disassociated before deleting the parent object.
@OnDissociate
can only be used on foreign key based many-to-one associations, for example:
- 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?
...
}
Although disassociation of child objects is caused by a one-to-many association (or inverse one-to-one) (that is, the parent object abandons some child objects. The one-to-many association here is BookStore.books
), the disassociation mode is configured for the inverse many-to-one association (here Book.store
). This design is to maintain similarity with configuring cascade properties of foreign keys in database DDLs.
For Jimmer, a one-to-many association must be bidirectional, so the many-to-one association that is the mirror image of a known one-to-many association is always known. So there is no problem with this design.
Dissociation Modes
The parameter of the OnDissociate
annotation in the above code is called the dissociation mode:
There are 5 modes for dissociating child objects
Name | Description |
---|---|
NONE (default) | Depend on the global configuration jimmer.default-dissociate-action-checking.
|
LAX | This option is only valid for pseudo foreign keys (please refer to Real and Fake Foreign Keys), otherwise it will be ignored, the same as CHECK. Dissociation operations are supported even if there are child objects. Even if the parent object is deleted (dissociation mode is also adopted by delete commands), dangling pseudo foreign keys of child objects are allowed (even if pseudo foreign keys are left dangling, the query system can still work normally). |
CHECK | If there are child objects, disassociation is not supported, the operation is prevented by throwing an exception. |
SET_NULL | Set the foreign key of the disassociated child object to null. The prerequisite is that the many-to-one associated property of the child object is nullable; otherwise, attempting this configuration will lead to an exception. |
DELETE | Delete the disassociated child objects. |
This article only introduces the configuration of OnDissociate. For how to use it further, please refer to Save Command/Dissociation Operations and Delete Commands.
Dynamic Overrides
Configuration specified by the annotation @OnDissociate
is called static configuration.
Sometimes, different businesses may have different requirements for dissociation operations. Therefore, dissociation configurations can be dynamically overridden at runtime.
-
- 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
)
}