级联关系定义

本章将介绍如何在KPojo实体类中定义级联关系。

级联关系注解

KPojo提供了@Cascade注解来定义级联关系,详见:📚注解配置 - @Cascade级联关系声明。

1. 一对多级联关系

本节将介绍如何在KPojo实体类中定义一对多级联关系。

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

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

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

以上代码中,Child实体类中的@Cascade注解声明了最简单的一对多级联关系。

@Cascade注解的第一个参数是Child实体类中的级联字段parentId,第二个参数是Parent实体类中的主键字段id。

至此,Parent和Child两个实体类之间的一对多级联关系定义完成。

如果需要通过多个字段进行级联关系定义,可以在@Cascade注解的第一个参数中使用逗号分隔多个级联字段,如下所示:

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

通常我们认为,没有注解定义的一端为维护端,也是级联关系中的父端,而注解声明的一端为被维护端,也是级联关系中的子端。 在级联关系中,父端的变化会影响子端,而子端的变化不会影响父端。

2.一对一级联关系

本节将介绍如何在KPojo实体类中定义一对一级联关系。

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

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

data class Profile(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var userId: Long? = null,
    var email: String? = null,
    var user: User? = null
) : KPojo

以上代码中,User实体类中的@Cascade注解声明了最简单的一对一级联关系。

@Cascade注解的第一个参数是User实体类中的主键字段id,第二个参数是Profile实体类中的级联字段userId。

至此,User和Profile两个实体类之间的一对一级联关系定义完成。

如果需要通过多个字段进行级联关系定义,可以在@Cascade注解的第一个参数中使用逗号分隔多个级联字段,如下所示:

data class User(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var name: String? = null,
    var email: String? = null,
    @Cascade(["id", "email"], ["userId", "email"])
    var profile: Profile? = null
) : KPojo

一对一级联关系中,注解可以只在一端声明,也可以在两端同时声明,但是只有一端声明时,没有注解定义的一端为维护端,也是级联关系中的父端。

3.多对多级联关系

本节将介绍如何在KPojo实体类中定义多对多级联关系。

通常,多对多级联关系需要通过中间表来实现,中间表中包含了两个实体类的主键字段。

首先,我们有User、Role以及Relation三个实体类,其中Relation实体类中包含了User和Role两个实体类的引用。

data class User(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var name: String? = null,
    var relations: List<Relation>? = listOf()
) : KPojo

data class Role(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var name: String? = null,
    var relations: List<Relation>? = listOf()
) : KPojo

data class Relation(
    @PrimaryKey(identity = true)
    var id: Long? = null,
    var userId: Long? = null,
    var roleId: Long? = null,
    @Cascade(["userId"], ["id"])
    var user: User? = null,
    @Cascade(["roleId"], ["id"])
    var role: Role? = null
) : KPojo

以上代码中,Relation实体类中的@Cascade注解声明了最简单的多对多级联关系。

@Cascade注解的第一个参数是Relation实体类中的级联字段userId,第二个参数是User实体类中的主键字段id。

@Cascade注解的第一个参数是Relation实体类中的级联字段roleId,第二个参数是Role实体类中的主键字段id。

至此,User、Role以及Relation三个实体类之间的多对多级联关系定义完成。

使用委托实现级联多对多跨中间表关系

级联功能中多对多关系中的目标属性通过委托方式来定义,需要放在class内声明,形如:

data class User(
    val id: Int? = null,
    val name: String? = null,
    // 多对多关系的中间表
    val relations: List<Relation>? = emptyList()
) : KPojo {
    // 多对多关系的目标表
    var roles: List<Role>? by manyToMany(::relations)
}