
room 要求所有实体(entity)和数据传输对象(pojo)必须具备一个可访问的公共构造函数,支持无参构造或参数名/类型与字段完全匹配的构造函数;本文详解两种合规写法并给出最佳实践建议。
room 要求所有实体(entity)和数据传输对象(pojo)必须具备一个可访问的公共构造函数,支持无参构造或参数名/类型与字段完全匹配的构造函数;本文详解两种合规写法并给出最佳实践建议。
在使用 Room 数据库时,当你定义一个用于 @Query 查询结果映射的复合数据类(如 GrumeBillesEntity),Room 会尝试通过反射实例化该类。若类中没有显式声明可用的公共构造函数,且字段均为非空类型、无默认值,就会抛出编译错误:
Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
你当前的 GrumeBillesEntity 是一个 data class,其两个属性 billes: List
✅ 正确解决方案(二选一)
方案一:为每个属性提供默认值(推荐用于简单场景)
data class GrumeBillesEntity(
@Embedded val billes: List<billeentity> = emptyList(),
@Relation(
parentColumn = "id_grume",
entityColumn = "id_grume"
)
val grume: Grume = Grume() // 注意:Grume 类也需有无参构造函数或默认值
) {
// 可选:显式主构造函数(增强可读性)
constructor(billes: List<billeentity>, grume: Grume) : this(billes, grume)
}</billeentity></billeentity>
⚠️ 注意事项:
- Grume 类本身也必须满足 Room 构造要求(例如:data class Grume(...) { constructor() : this(defaults...) } 或所有字段带默认值);
- @Embedded 字段若为集合(如 List
),Room 不支持直接嵌入集合——这是关键隐性限制!@Embedded 仅适用于单个嵌套对象,而非列表。你当前查询中 b.* + g.* 的多行结果合并为单个 GrumeBillesEntity 实例,在语义上存在歧义,Room 无法自动将多条数据库记录聚合为 List 。
方案二:显式声明无参构造函数(更清晰、更安全)
data class GrumeBillesEntity(
@Embedded val billes: List<billeentity>,
@Relation(
parentColumn = "id_grume",
entityColumn = "id_grume"
)
val grume: Grume
) {
// 提供 Room 所需的无参构造函数
constructor() : this(emptyList(), Grume())
}</billeentity>
此方式明确分离了“Room 实例化所需构造”与“业务逻辑使用的构造”,语义更清晰,也便于后续扩展。
⚠️ 关键提醒:@Embedded 不适用于 List
Room 的 @Embedded 注解仅支持嵌入单个对象,不能用于 List 或其他集合类型。你当前 SQL 查询通过 JOIN + GROUP BY 试图将多个 bille 行聚合到一个 grume 下,但 Room 无法自动将多行映射为 List
✅ 正确做法示例:
// Step 1: 查询 Grume(主表)
@Query("SELECT * FROM grume WHERE id_bordereau = :idBordereau")
suspend fun getGrumesByBordereau(idBordereau: String): List<grume>
// Step 2: 为每个 Grume 获取关联的 Bille 列表(Room 自动填充)
@Entity
data class Grume(
@PrimaryKey val id_grume: Long,
// ... other fields
)
@Entity
data class Bille(
@PrimaryKey val id_bille: Long,
val id_grume: Long,
// ... other fields
)
data class GrumeWithBilles(
@Embedded val grume: Grume,
@Relation(
parentColumn = "id_grume",
entityColumn = "id_grume"
)
val billes: List<bille>
)</bille></grume>
✅ 总结
- 所有被 Room 用作查询返回类型的 POJO 必须提供公共、无参或参数匹配的构造函数;
- 优先为属性设置安全默认值(如 emptyList()、Grume()),或显式添加 constructor();
- 避免误用 @Embedded 处理集合——改用 @Relation 实现一对多关联;
- 确保关联实体(如 Grume、Bille)自身也满足 Room 构造约束。
遵循以上原则,即可彻底解决该编译错误,并构建健壮、可维护的 Room 数据层。











