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

Android Room构建1对多关联时遭遇SQLite错误与类型匹配问题

解决Room 1对多关联的三个核心错误

针对你遇到的Room关联问题,以下是逐个错误的根源分析和修复方案:

1. 类型亲和性不匹配警告

错误原因:
你在EventRating中直接存储HrEvent对象,通过转换器将其转为字符串(事件名称),但关联时用父表的id(整数类型)和子表的event(字符串类型)匹配,导致类型不兼容。

修复方案:
将EventRating中的event字段改为存储HrEvent的主键id(整数类型),并添加外键约束保证数据一致性:

@Entity(
    foreignKeys = [ForeignKey(
        entity = HrEvent::class,
        parentColumns = ["id"],
        childColumns = ["eventId"],
        onDelete = ForeignKey.CASCADE // 删除事件时自动删除关联评分
    )]
)
@TypeConverters(MyTypeConverter::class)
data class EventRating(
    @PrimaryKey(autoGenerate = true)
    var id: Int,
    @ColumnInfo(name = "date")
    var date: Date,
    var value: Int,
    @ColumnInfo(name = "user")
    var user: User,
    @ColumnInfo(name = "eventId") // 改为存储事件ID
    var eventId: Int
)

同时更新EventWithEventRatings的关联配置:

data class EventWithEventRatings(
    @Embedded
    val event: HrEvent,
    @Relation(
        parentColumn = "id",
        entityColumn = "eventId" // 对应EventRating的eventId字段
    )
    val eventRatings: List<EventRating>
)

删除MyTypeConverter中关于HrEvent的转换方法(不再需要):

// 移除以下两个方法
// fun fromHrEvent(event: HrEvent): String { ... }
// fun toHrEvent(eventName: String): HrEvent { ... }

2. 「no such table: EventRating」错误

错误原因:
你的EventRatingDatabase仅声明了EventRating为实体类,未包含HrEvent,且未声明HrEventDao,导致Room没有生成HrEvent表,同时关联查询找不到依赖的表。

修复方案:
更新数据库注解,包含所有需要的实体类,并添加对应的Dao声明:

@Database(entities = [HrEvent::class, EventRating::class], version = 1)
@TypeConverters(MyTypeConverter::class)
abstract class EventRatingDatabase : RoomDatabase() {
    abstract val hrEventDao: HrEventDao // 添加HrEventDao
    abstract val eventRatingDao: EventRatingDao

    // 保持原Callback代码不变
}

3. 「Not sure how to convert a Cursor to this method's return type」错误

错误原因:
一是之前的类型不匹配导致Room无法映射结果;二是查询方法返回List<EventWithEventRatings>,但根据WHERE id = :eventID的条件,主键查询只会返回单个结果,类型不匹配。

修复方案:
修改HrEventDao的查询方法返回类型为单个EventWithEventRatings:

@Dao
interface HrEventDao {
    @Upsert
    suspend fun upsert(hrEvent: HrEvent)

    @Delete
    suspend fun delete(hrEvent: HrEvent)

    @Transaction
    @Query("SELECT * FROM HrEvent WHERE id = :eventID")
    suspend fun getEventWithEventRatings(eventID: Int): EventWithEventRatings // 改为单个对象
}

最后注意事项

  • 由于修改了实体结构,确保数据库使用fallbackToDestructiveMigration()(你已配置),这样重新运行App时会重建数据库,避免迁移错误。
  • 检查依赖注入的AppModule,确保提供的数据库包含所有Dao的声明。

内容的提问来源于stack exchange,提问作者David Natzkin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:35:05