级联更新

本文将指导您如何使用Kronos的级联更新功能。

1. 一对一级联关系

本节将介绍对于Kronos中定义的一对一级联关系的级联更新。

数据类定义

我们定义User和Profile两个实体类,User实体类中包含了一个Profile实体类的引用,Profile实体类中包含了一个User实体类的引用。

User.kt

data class User(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var profileName: String? = null,
    @Cascade(["profileName"], ["name"])
    var profile: Profile? = null
)

Profile.kt

data class Profile(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var userName: String? = null,
    @Cascade(["userName"], ["name"])
    var user: User? = null
)

级联更新

更新User或Profile实体都可以进行级联更新,级联更新会自动修改为级联创建的实体的引用属性(支持自增主键和多层级级联关系)。

User(
    id = 1,
    name = "user" //这里会级联更新Profile的userName字段
).update().by { it.id }.execute()

或者:

Profile(
    id = 1,
    name = "profile" //这里会级联更新User的profileName字段
).update().by { it.id }.execute()

2. 一对多级联关系

一对多关系和一对一关系的用法类似。

数据类定义

首先,我们定义以下的Parent和Child两个实体类,Parent实体类中包含了一个Child实体类的集合,Child实体类中包含了一个Parent实体类的引用。

Parent.kt

data class Parent(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var name: String? = null,
    var children: List<Child> = listOf()
)

Child.kt

data class Child(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var name: String? = null,
    var parentName: String? = null,
    @Cascade(["parentName"], ["name"])
    var parent: Parent? = null
)

级联更新

使用KPojo.update()方法,可以实现一对多级联关系的级联更新。

在Kronos中的一对多更新时,仅支持Parent -> Child方向的级联更新。

在级联更新时不需要指定Child实体的parentId,级联更新会自动修改为Child实体的parentId(支持自增主键和多层级级联关系)。

Parent(
    id = 1,
    name = "parent" //这里会级联更新Child的parentName字段
).update().by { it.id }.execute()

以下是一个更加复杂的、层级更深的例子:

School.kt

data class School(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var groupClasses: List<GroupClass> = listOf()
)

GroupClass.kt

data class GroupClass(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var schoolName: String? = null,
    @Cascade(["schoolName"], ["name"])
    var school: School? = null,
    var students: List<Student> = listOf()
)

Student.kt

data class Student(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var groupClassName: Name? = null,
    var schoolName: String? = null,
    @Cascade(["groupClassName", "schoolName"], ["name", "schoolName"])
    var groupClass: GroupClass? = null
)
School(
    id = 1,
    name = "school" //这里会级联更新GroupClass和Student的schoolName字段
).update().by { it.id }.execute()

3. 多对多级联关系

通过manyToMany委托,Kronos简化多对多关系为一对多关系,并为您自动创建关联表记录,详见:📚级联关系定义 - 使用委托实现级联多对多跨中间表关系。

数据类定义

首先我们定义User、Role、Relation三个实体类,其中Relation实体类中包含了User和Role两个实体类的引用,User和Role通过manyToMany委托关联。

User.kt

data class User(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var relations: List<Relation> = listOf()
){
    var roles: List<Role> by manyToMany(::relations)
}

Role.kt

data class Role(
    @PrimaryKey
    var id: Long? = null,
    var name: String? = null,
    var relations: List<Relation> = listOf()
){
    var users: List<User> by manyToMany(::relations)
}

Relation.kt

data class Relation(
    @PrimaryKey
    var id: Long? = null,
    var userName: String? = null,
    var roleName: String? = null,
    @Cascade(["userName", "roleName"], ["name", "name"])
    var user: User? = null,
    @Cascade(["userName", "roleName"], ["name", "name"])
    var role: Role? = null
)

级联更新

更新User或Role实体都可以进行级联更新,并自动更新级联创建的中间表实体的引用属性赋值。

这里我们并不会自动级联更新级联的另一端的实体,因为我们无法保证级联的另一端的实体是否被其他记录所引用,因此该功能属于业务层面的范畴,需要用户自行增加更新逻辑。

User(
    id = 1,
    name = "user" //这里会级联更新Relation的userName字段
).update().by { it.id }.execute()

或者:

Role(
    id = 1,
    name = "role" //这里会级联更新Relation的roleName字段
).update().by { it.id }.execute()