如何在Android中配置包含嵌套实体的Room数据库?
在Room中处理包含嵌套实体列表的配置
针对你提供的API响应结构(Teacher包含多个Student),Room提供两种常用解决方案,可根据业务需求选择:
方案一:使用TypeConverter(适合无需单独操作Student的场景)
如果不需要单独查询、更新Student数据,仅需将整个Teacher对象(包含学生列表)作为整体存储/读取,用TypeConverter将学生列表转为JSON字符串存储是最简单的方式。
1. 定义数据类
// Student数据类 data class Student( val contact: Long, val name: String ) // Teacher实体类 @Entity(tableName = "teachers") data class Teacher( @PrimaryKey val id: String, val teacherName: String, val subject: String, val status: String, // 学生列表,通过TypeConverter转成JSON存储 val student_enrolled: List<Student> )
2. 创建TypeConverter
class Converters { private val gson = Gson() @TypeConverter fun fromStudentList(students: List<Student>): String { return gson.toJson(students) } @TypeConverter fun toStudentList(studentJson: String): List<Student> { val type = object : TypeToken<List<Student>>() {}.type return gson.fromJson(studentJson, type) } }
3. 配置Room数据库
@Database(entities = [Teacher::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun teacherDao(): TeacherDao }
4. Dao接口
@Dao interface TeacherDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertTeachers(teachers: List<Teacher>) @Query("SELECT * FROM teachers") suspend fun getAllTeachers(): List<Teacher> }
方案二:使用一对多关系(适合需要单独操作Student的场景)
如果需要单独查询某个老师的学生、更新学生信息等,建议将Teacher和Student分别存为两张表,用Room的@Relation注解建立关联。
1. 定义实体类
// Teacher实体,主键为id @Entity(tableName = "teachers") data class Teacher( @PrimaryKey val id: String, val teacherName: String, val subject: String, val status: String ) // Student实体,包含teacherId作为外键关联Teacher @Entity( tableName = "students", foreignKeys = [ForeignKey( entity = Teacher::class, parentColumns = ["id"], childColumns = ["teacherId"], onDelete = ForeignKey.CASCADE )], indices = [Index(value = ["teacherId"])] ) data class Student( @PrimaryKey(autoGenerate = true) val studentId: Long = 0, val contact: Long, val name: String, val teacherId: String // 关联Teacher的id )
2. 创建关联数据类
// 用来封装Teacher和对应的学生列表 data class TeacherWithStudents( @Embedded val teacher: Teacher, @Relation( parentColumn = "id", entityColumn = "teacherId" ) val students: List<Student> )
3. 配置Room数据库
@Database(entities = [Teacher::class, Student::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun teacherDao(): TeacherDao }
4. Dao接口(带事务查询)
@Dao interface TeacherDao { // 插入Teacher和对应的Students,用事务保证原子性 @Transaction suspend fun insertTeacherWithStudents(teacher: Teacher, students: List<Student>) { insertTeacher(teacher) insertStudents(students) } @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertTeacher(teacher: Teacher) @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertStudents(students: List<Student>) // 查询所有老师及其学生列表 @Transaction @Query("SELECT * FROM teachers") suspend fun getAllTeachersWithStudents(): List<TeacherWithStudents> // 查询指定老师的学生列表 @Transaction @Query("SELECT * FROM teachers WHERE id = :teacherId") suspend fun getTeacherWithStudents(teacherId: String): TeacherWithStudents? }
注意事项
- 使用TypeConverter时,需引入Gson依赖(在build.gradle中添加
implementation 'com.google.code.gson:gson:2.10.1') - 一对多关系中,外键的
onDelete策略可根据业务需求调整,CASCADE表示删除Teacher时自动删除关联的Student - 所有数据库操作建议在协程中执行,避免阻塞主线程
内容的提问来源于stack exchange,提问作者Deepak Gupta
相关产品推荐
相关产品推荐

