You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中为Room数据库添加模型类并分表存储数据

实现Room数据库分表存储与查询

我有一个需要导入Room数据库的保存模型,要求将List<Images>以外的信息存入名为ReplacedData的独立表,Images列表存入Images表,请问该如何实现,对应的查询语句是什么?
模型JSON如下:

{"AccountNumber": "S234567","ActionRequiredID": "6,7","AdditionalRemarks": "","AndroidVersion": "31","AntennaTypeID": 6,"AppVersion": "2.1.3","CTRatio": "","CategoryID": 1,"CurrentMeterSealNumber": "thhjj","CycleName": "Nov-2022","EndTime": "2022-11-07 12:05:51","ICCIDNumber": "thb","Images": [{"ID": 0,"PicFormat": "jpg","PicName": "S23456-TRS_6-TI1-team1_2022-11-07_17-35-05.jpg","PicPath": "/storage/emulated/0/Download/team1/MReader/troubleshoot/Troubleshooting-Nov-2022/Photos/","PicSize": "36 KB","PictureTypeID": 18,"ServiceID": 5,"SurveyID": 6}],"IsGPSEnabled": true,"IsLiveGPS": true,"IsOnline": true,"Latitude": 11.0501224,"LocationAccuracy": 9.133,"LocationProvider": "fused","Longitude": 76.9678775,"MeterLocationID": 1,"MeterModelID": 5,"MeterSerialNumber": "61604448","NewMeterSealNumber": "","PingTestID": 1,"ReasonForFailureID": "5","ReasonID": 39,"Remarks": "","Seal1": "","Seal2": "","Seal3": "","Seal4": "","ServiceID": 5,"SignalLevelID": 2,"SimInField": "cghb","StartTime": "2022-11-07 12:05:05","StatusID": 12,"StatusTroubleshootID": 4,"UserID": 161,"WorkOrderID": 6,"WorkOrderNumber": "TRS_6","reason": "Completed","status": "Completed"}

1. 定义Room实体类

1.1 ReplacedData主表实体

主表设WorkOrderID作为主键(业务上唯一),把原JSON里除Images外的所有字段都映射进来:

@Entity(tableName = "ReplacedData")
data class ReplacedData(
    @PrimaryKey val WorkOrderID: Int,
    val AccountNumber: String,
    val ActionRequiredID: String,
    val AdditionalRemarks: String,
    val AndroidVersion: String,
    val AntennaTypeID: Int,
    val AppVersion: String,
    val CTRatio: String,
    val CategoryID: Int,
    val CurrentMeterSealNumber: String,
    val CycleName: String,
    val EndTime: String,
    val ICCIDNumber: String,
    val IsGPSEnabled: Boolean,
    val IsLiveGPS: Boolean,
    val IsOnline: Boolean,
    val Latitude: Double,
    val LocationAccuracy: Double,
    val LocationProvider: String,
    val Longitude: Double,
    val MeterLocationID: Int,
    val MeterModelID: Int,
    val MeterSerialNumber: String,
    val NewMeterSealNumber: String,
    val PingTestID: Int,
    val ReasonForFailureID: String,
    val ReasonID: Int,
    val Remarks: String,
    val Seal1: String,
    val Seal2: String,
    val Seal3: String,
    val Seal4: String,
    val ServiceID: Int,
    val SignalLevelID: Int,
    val SimInField: String,
    val StartTime: String,
    val StatusID: Int,
    val StatusTroubleshootID: Int,
    val UserID: Int,
    val WorkOrderNumber: String,
    val reason: String,
    val status: String
)

1.2 Images子表实体

图片表加WorkOrderID作为外键,关联主表的主键,确保图片和工单绑定;主键用自增ID,原JSON里的ID设默认值:

@Entity(
    tableName = "Images",
    foreignKeys = [ForeignKey(
        entity = ReplacedData::class,
        parentColumns = ["WorkOrderID"],
        childColumns = ["WorkOrderID"],
        onDelete = ForeignKey.CASCADE // 删除工单时自动删除关联图片
    )]
)
data class Images(
    @PrimaryKey(autoGenerate = true) val ID: Int = 0,
    val PicFormat: String,
    val PicName: String,
    val PicPath: String,
    val PicSize: String,
    val PictureTypeID: Int,
    val ServiceID: Int,
    val SurveyID: Int,
    val WorkOrderID: Int // 外键,关联工单ID
)

2. 定义DAO数据访问接口

写好插入和查询的方法,用@Transaction实现主表子表关联查询:

@Dao
interface ReplacedDataDao {
    // 插入单条工单数据
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertReplacedData(replacedData: ReplacedData)

    // 批量插入图片
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertImages(images: List<Images>)

    // 查询指定工单的完整数据(工单+关联图片)
    @Transaction
    @Query("SELECT * FROM ReplacedData WHERE WorkOrderID = :workOrderId")
    suspend fun getReplacedDataWithImages(workOrderId: Int): ReplacedDataWithImages?

    // 查询所有工单的完整数据
    @Transaction
    @Query("SELECT * FROM ReplacedData")
    suspend fun getAllReplacedDataWithImages(): List<ReplacedDataWithImages>

    // 单独查询某工单的图片
    @Query("SELECT * FROM Images WHERE WorkOrderID = :workOrderId")
    suspend fun getImagesByWorkOrderId(workOrderId: Int): List<Images>
}

// 关联数据类,用于封装工单+图片的组合结果
data class ReplacedDataWithImages(
    @Embedded val replacedData: ReplacedData,
    @Relation(
        parentColumn = "WorkOrderID",
        entityColumn = "WorkOrderID"
    )
    val images: List<Images>
)

3. 定义Room数据库类

声明包含的实体类,提供DAO实例:

@Database(entities = [ReplacedData::class, Images::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
    abstract fun replacedDataDao(): ReplacedDataDao

    // 单例实现(按需调整)
    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null
        fun getDatabase(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "app_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

4. 数据插入逻辑

解析JSON后,分别插入主表和子表:

// 假设已将JSON解析为OriginalModel类
suspend fun insertOriginalModel(originalModel: OriginalModel, dao: ReplacedDataDao) {
    // 构建工单实体并插入
    val replacedData = ReplacedData(
        WorkOrderID = originalModel.WorkOrderID,
        AccountNumber = originalModel.AccountNumber,
        // 其他字段依次对应赋值...
        status = originalModel.status
    )
    dao.insertReplacedData(replacedData)

    // 构建图片实体列表,绑定当前工单ID后批量插入
    val images = originalModel.Images.map { img ->
        Images(
            PicFormat = img.PicFormat,
            PicName = img.PicName,
            PicPath = img.PicPath,
            PicSize = img.PicSize,
            PictureTypeID = img.PictureTypeID,
            ServiceID = img.ServiceID,
            SurveyID = img.SurveyID,
            WorkOrderID = originalModel.WorkOrderID
        )
    }
    dao.insertImages(images)
}

5. 常用查询语句

5.1 查询指定工单的完整数据

Room自动关联子表,对应SQL:

SELECT * FROM ReplacedData WHERE WorkOrderID = :workOrderId

直接调用DAO的getReplacedDataWithImages(workOrderId)即可拿到工单+图片的组合数据。

5.2 查询所有工单的完整数据

对应SQL:

SELECT * FROM ReplacedData

调用getAllReplacedDataWithImages()返回所有工单及其关联图片。

5.3 单独查询某工单的图片

对应SQL:

SELECT * FROM Images WHERE WorkOrderID = :workOrderId

调用getImagesByWorkOrderId(workOrderId)返回该工单下的所有图片。


内容的提问来源于stack exchange,提问作者Abhijith Warrier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:55:46