Room数据库仅查询指定列时报错缺少POJO非空字段,原因及解决方法
报错原因拆解
核心触发逻辑
你当前的DAO查询直接返回了被@Entity标注的Room实体类Item_get,Room对实体类的映射规则有明确要求:查询返回的结果列,必须能覆盖所有实体里标注为非空、原始类型(int、float、boolean等)的字段。
这类原始类型字段不存在合法的null默认值,如果查询没有返回对应列,Room无法完成字段赋值,因此会直接中断编译抛出错误。
为什么报错只提示缺失部分字段,不是全字段
Room的字段校验是分场景触发的,只会对必须强制赋值的字段做强校验:
- 报错列表里出现的
id、to_shop、cat_food、cat_package全是原始int类型,属于无合法空默认值的非空字段,没有对应返回列时会直接触发校验失败; - 类里剩下的其他字段,比如
price、value是包装类Double,name_product、date_buy、date_exp是引用类型String,这些字段天然支持null值,哪怕查询没有返回对应列,Room只会自动给它赋null,不会触发编译错误,因此自然不会被列在报错提示里。
你看到报错列表里出现的
amount字段,是因为最早触发报错的查询语句没有返回amount列;当你把amount加到SELECT列表里之后,这个字段的校验就会自动通过。
为什么所有部分字段查询都报错
你所有查询部分字段的DAO方法,返回值都写的是Item_get实体类。只要返回值类型是被@Entity标注的Room实体,Room就会按照全实体字段的映射规则做校验,和你实际查询了几列没有关系,因此所有这类部分查询都会触发同样的报错。
空构造函数的影响
你补充的空构造函数完全不会导致报错,反而是Room对实体类的强制要求——Room需要通过空构造函数初始化实体实例,再逐字段完成数据赋值,这个写法是完全符合官方规范的。
正确的解决方式
- 不要用数据库实体类接收部分查询的结果,单独创建只包含所需返回字段的纯POJO类(不需要加
@Entity注解),示例代码:
public class ProductNameAmountPojo { @ColumnInfo(name = "name_product") public String name_product; @ColumnInfo(name = "amount") public int amount; }
- 将DAO方法的返回值替换为这个纯POJO的对应类型,比如:
@Query("SELECT name_product, amount FROM Table WHERE to_shop = 1 AND food_type = :category") LiveData<List<ProductNameAmountPojo>> getCategoryThingsToBuy(int category);
这种方式既不会触发字段校验报错,还能避免SELECT *查询带来的不必要IO性能损耗,尤其适合数据量较大的表结构。
注意:不要为了绕过报错把实体里的原始类型字段全部改成可空包装类,这种做法会破坏实体原本的非空数据约束,后续写入数据时反而会引入空值异常。
内容的提问来源于stack exchange,提问作者Rivke
相关产品推荐
相关产品推荐

