An overview of the

Sqlite is a relational database, so object relationships are an important part of it. For example, we define data with forests and trees, and forests contain trees. The forest defined at this point should contain a tree object, which is the one-to-many object relationship between the forest and trees

Relationship types

There are four types of relationships between multiple objects:

  • One to one
  • More than a pair of
  • Many to many
  • nested

One to one

A father has a son. This is a one-to-one relationship

code

class RoomRelativeActivity : CustomAdapterActivity() {
    private lateinit var database: OurRoomDatabase

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        database=Room.databaseBuilder(this,OurRoomDatabase::class.java,"parentsun").build()
    }
    override fun getAdapterDatas(a): MutableList<ItemData> = mutableListOf(
        ItemData(title = "Insert a dad.") {
            lifecycleScope.launch {
                val parent = Parent(Little Daddy.)
                database.parentSunDao().insertParent(parent)
                it.itemData.content="Insert successful"
                it.itemData.notifyDataSetChange()
            }
        },
        ItemData(title = "Insert a son."){
               lifecycleScope.launch {
                   val sun=Sun(Big Head boy.1)
                   database.parentSunDao().insertSun(sun)
                   it.itemData.run {
                       content="Insert successful"
                       notifyDataSetChange()
                   }
               }
        },
        ItemData(title = "Query data"){
            lifecycleScope.launch {
                var parentAndSun = database.parentSunDao().queryParent(1)
                val content = "The father is:${parentAndSun.parent}\n The son is:${parentAndSun.sun}"
                it.itemData.content=content
                it.itemData.notifyDataSetChange()
            }
        }
    )

    override fun showFirstItem(a): Boolean = false
}
@Dao
interface ParentSonDao {
    @Transaction
    @Insert
    suspend fun insertParent(parent: Parent)// Insert father

    @Insert
    suspend fun insertSun(sun: Sun)// Insert the son

    /** * query parent and son combinations */
    @Transaction
    @Query("select * from Parent where parentId=:parentId")ParentAndSunRef = ParentAndSunRef (ParentAndSunRef)
    suspend fun queryParent(parentId: Long): ParentAndSunRef
}

/** * Parent = 'Parent'; /** * Parent = 'Parent'
data class ParentAndSunRef(// We don't need to add @entity annotation to ParentAndSunRef
    @Embedded
    val parent: Parent,//
    @Relation(
        parentColumn = "parentId",// Primary key parentId entityColumn ="hisparentId"// the parent must store some unique id of the son hisparentId.)
    val sun: Sun
)

/** ** father */
@Entity
data class Parent(var name: String) {
    @PrimaryKey(autoGenerate = true)
    var parentId: Long? = null
}

/**
 * 儿子
 */
@Entity
data class Sun(var name: String,var hisparentId:Long) {
    @PrimaryKey(autoGenerate = true)
    var sunId: Long? = null
}
Copy the code

Implementation effect

Database structure

  1. The Parent table

  1. Sun table

More than a pair of

In the last video you had an only child, so you have one father for one son, so in this case you’re not an only child, so one father can have multiple sons.

For example, when Mother Apron gives birth to big Head’s son, then small head’s father has two sons. The son’s options in the relation class cannot be an object, but should be a list.

So one-to-many is basically the same as one-to-one, except that the sons are represented by a list.

code


class OneToManyActivity : CustomAdapterActivity() {

    private lateinit var database: OurRoomDatabase

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        database = Room.databaseBuilder(this,OurRoomDatabase::class.java,"parent1andsun1").build()
    }
    override fun getAdapterDatas(a): MutableList<ItemData> = mutableListOf(
        ItemData("Insert a dad."){
            lifecycleScope.launch {
                val parent=Parent1(Little Daddy.)
                database.parent1AndSun1Dao().insertParent1(parent)
                it.itemData.run {
                    content="Insert successful"
                    notifyDataSetChange()
                }
            }
        },
        ItemData("Insert a son."){
            lifecycleScope.launch {
                val sun = Sun1(Big Head boy.1)
                database.parent1AndSun1Dao().insertSun1(sun)
            }
            it.itemData.run {
                content="Insert successful"
                notifyDataSetChange()
            }
        },
        ItemData("Insert second son."){
            lifecycleScope.launch {
                val sun = Sun1("Big Head's little brother.".1)
                database.parent1AndSun1Dao().insertSun1(sun)
            }
            it.itemData.run {
                content="Insert successful"
                notifyDataSetChange()
            }
        },
        ItemData(title = "Query 1 father and 2 sons"){
            lifecycleScope.launch {
                val parentAndSunRef = database.parent1AndSun1Dao().queryParent1AndSun1(1)
                val con = "The father is:${parentAndSunRef.parent.name} " +
                        "\n The first son was:${parentAndSunRef.sun1s[0].name} " +
                        "\n The second son was:${parentAndSunRef.sun1s[1].name}"
                it.itemData.run {
                    content=con
                    notifyDataSetChange()
                }
            }
        }
    )

    override fun showFirstItem(a): Boolean =false
}
@Dao
interface Parent1AndSun1Dao{
    @Insert
    suspend fun insertParent1(parent: Parent1)
    @Insert
    suspend fun insertSun1(parent: Sun1)
    /** * query the set of father and son, there must be@TransactionNote that the purpose is to preserve atomic operation */
    @Transaction
    @Query("select * from Parent1 where parentId=:parentId")
    suspend fun queryParent1AndSun1(parentId:Long):Parent1AndSun1Ref
}
@Entity
data class Parent1(var name:String){
    @PrimaryKey(autoGenerate = true)
    var parentId:Long? =null
}
@Entity
data class Sun1(var name:String,var refparentId:Long) {@PrimaryKey(autoGenerate = true)
    var sunId:Long? =null

}
data class Parent1AndSun1Ref(
    @Embedded
    val parent:Parent1,
    @Relation(
        parentColumn = "parentId"ParentColumn entityColumn ="refparentId"
    )
    val sun1s:List<Sun1>
)
Copy the code

The effect

Many to many

The above example is one father for multiple sons, but we all know that the relationship between big head’s son, small head’s father, and Lao Wang next door is well-known. There may be a many-to-many relationship, and this is a many-to-many relationship.

To implement this many-to-many relationship, you need to define multiple relationships,

For example, if a father has more than one son, he or she has to define the relationship classes of Parent2Suns;

The case that a son has two fathers needs to define the relationship class of Sun2Parents;

code


class ManyToManyActivity : CustomAdapterActivity() {
    private lateinit var database: OurRoomDatabase

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        database = Room.databaseBuilder(this, OurRoomDatabase::class.java, "parent2AndSun2").build()
    }

    override fun getAdapterDatas(a): MutableList<ItemData> = mutableListOf(
        ItemData(title = "Plug in the little daddy.") {
            lifecycleScope.launch {
                val parent = Parent2(Little Daddy..1)
                database.parent2AndSun2Dao().insertParent2(parent)
            }
        },
        ItemData(title = "Into the king next door.") {
            lifecycleScope.launch {
                val parent = Parent2("Next door Lao Wang".1)
                database.parent2AndSun2Dao().insertParent2(parent)
            }
        },
        ItemData(title = "Insert the big head son.") {
            lifecycleScope.launch {
                val sun = Sun2(Big Head boy.1)
                database.parent2AndSun2Dao().insertSun2(sun)
            }
        },
        ItemData(title = "Insert the big head's brother.") {
            lifecycleScope.launch {
                val sun = Sun2("Big Head's little brother.".1)
                database.parent2AndSun2Dao().insertSun2(sun)
            }
        },
        ItemData(title = "Query son") {
            lifecycleScope.launch {
                val parent = database.parent2AndSun2Dao().queryParent(1)
                logEE(parent.toString())
            }
        }
    )

    override fun showFirstItem(a): Boolean = false
}
@Dao
interface Parent2AndSun2Dao {
    @Insert
    suspend fun insertParent2(parent: Parent2)

    @Insert
    suspend fun insertSun2(sun: Sun2)

    @Transaction
    @Query("select * from Parent2 where combineId=:combineId")
    suspend fun queryParent(combineId: Long): Parent2Sun2Ref

    @Transaction
    @Query("select * from Sun2 where combineId=:combineId")
    suspend fun querySun(combineId: Long): Sun2Parent2Ref
}

@Entity
data class Parent2(var name: String, var combineId: Long) {
    @PrimaryKey(autoGenerate = true)
    var parentId: Long? = null
}

@Entity
data class Sun2(var name: String, var combineId: Long) {
    @PrimaryKey(autoGenerate = true)
    var sunId: Long? = null
}

data class Parent2Sun2Ref(
    @Embedded
    var parent: Parent2,
    @Relation(
        parentColumn = "combineId",
        entityColumn = "combineId"
    )
    var sun: List<Sun2>
)

data class Sun2Parent2Ref(
    @Embedded
    var sun: Sun2,
    @Relation(
        parentColumn = "combineId",
        entityColumn = "combineId"
    )
    var parent: List<Parent2>
)
Copy the code

rendering

nested

In the three summaries above, we use @embdded and @Relation annotations to achieve relational mapping between databases.

In fact, @relation and @embdded alone can still achieve object nesting.

For example, in this example, we nested Sun3 with @embdded in Parent3. Fields in Sun3 will be copied to the table in Parent3.

code

package com.ananananzhuo.roomdemo.embdded

import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import androidx.room.*
import com.ananananzhuo.mvvm.activity.CustomAdapterActivity
import com.ananananzhuo.mvvm.bean.bean.ItemData
import com.ananananzhuo.roomdemo.OurRoomDatabase
import kotlinx.coroutines.launch

/** * author :mayong * function: nested between objects * date :2021/9/12 **/
class EmbddedActivity : CustomAdapterActivity() {
    private lateinit var database: OurRoomDatabase

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        database = Room.databaseBuilder(this,OurRoomDatabase::class.java,"parent3AndSun3").build()
    }
    override fun getAdapterDatas(a): MutableList<ItemData> = mutableListOf(
        ItemData(title = "Plug in the little daddy."){
            lifecycleScope.launch {
                database.parent3AndSun3Dao().insertParent(Parent3(Little Daddy., Sun3(Big Head boy)))
            }
        },
        ItemData(title = "Check out daddy Head."){
            lifecycleScope.launch {
                val parent3 = database.parent3AndSun3Dao().queryParent(1)
                it.itemData.run {
                    content="Father's name:${parent3.parentName}\n Son's name:${parent3.sun.sunName}"
                    notifyDataSetChange()
                }
            }
        }
    )

    override fun showFirstItem(a): Boolean=false
}
@Dao
interface Parent3Sun3Dao {
    @Insert
    suspend fun insertParent(parent3: Parent3)

    @Insert
    suspend fun insertSun(sun: Sun3)

    @Query("select * from Parent3 where parentId=:parentId")
    suspend fun queryParent(parentId: Long): Parent3
}

@Entity
data class Parent3(
    var parentName: String,
    @Embedded
    var sun: Sun3
){
    @PrimaryKey(autoGenerate = true)
    var parentId: Long? = null
}

@Entity
data class Sun3(
    var sunName: String
){
    @PrimaryKey(autoGenerate = false)
    var sunId: Long? = null
}
Copy the code

The structure of a table after data is inserted

Insert data into parent table structure:

Table structure of the son:

No data is actually inserted into the son’s table