如何解决Room报错“Entities and POJOs must have a usable public constructor”
问题:Room编译报错“Entities and POJOs must have a usable public constructor”
编译基于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).
该报错出现在两个实体类中,相关代码如下:
User.java
@Entity(tableName = "user") public class User { @NonNull @PrimaryKey(autoGenerate = true) private long employee_id = 0; @ColumnInfo(name="agency_id") private String agency_id = ""; @ColumnInfo(name="user_id") private String user_id = ""; @ColumnInfo(name="row_id") private String row_id = ""; @ColumnInfo(name="csc_card_number") private String csc_card_number = ""; @ColumnInfo(name="create_date") private String create_date = ""; @ColumnInfo(name = "surname2") public String surname2 = ""; @ColumnInfo(name = "surname1") public String surname1 = ""; @ColumnInfo(name = "user_name") public String user_name = ""; public User(long employee_id, String agency_id, String user_id, String row_id, String csc_card_number, String create_date, String surname2, String surname1, String user_name) { this.employee_id = employee_id; this.agency_id = agency_id; this.user_id = user_id; this.row_id = row_id; this.csc_card_number = csc_card_number; this.create_date = create_date; this.surname2 = surname2; this.surname1 = surname1; this.user_name = user_name; } //Empty constructor public User(){ } // 以下为getter/setter方法,省略重复内容 public long getEmployee_id() { return employee_id; } public void setEmployee_id(long employee_id) { this.employee_id = employee_id; } // ... 其余getter/setter保持不变 }
UserAuth.java
@Entity(tableName = "userAuth") public class UserAuth { public UserAuth(long user_id, String rowid, long authentication_group_id, long authentication_type_id, String login, String password) { this.user_id = user_id; this.rowid = rowid; this.authentication_group_id = authentication_group_id; this.authentication_type_id = authentication_type_id; this.login = login; this.password = password; } //Empty constructor public UserAuth(){ } @PrimaryKey private long user_id = 0; @ColumnInfo(name = "rowid") private String rowid = ""; @ColumnInfo(name = "authentication_group_id") private long authentication_group_id = 0; @ColumnInfo (name = "auhentication_type_id") private long authentication_type_id = 0; @ColumnInfo(name = "login") private String login = ""; @ColumnInfo(name = "password") private String password = ""; // 以下为getter/setter方法,省略重复内容 public long getUser_id() { return user_id; } public void setUser_id(long user_id) { this.user_id = user_id; } // ... 其余getter/setter保持不变 }
Database类(pkg_users.java)
@androidx.room.Database( entities = { User.class, UserAuth.class }, version = 6 ) @TypeConverters({DateConverter.class}) public abstract class pkg_users extends RoomDatabase { public static pkg_users buildDataBase(final Context context){ return Room.databaseBuilder( context, pkg_users.class, AppConstant.PKG_USERS_DB) .allowMainThreadQueries().setJournalMode(RoomDatabase.JournalMode.TRUNCATE) .fallbackToDestructiveMigration().build(); } public abstract UserDao userUiContractDaoDAO(); }
DAO类(UserDao.java)
@Dao public interface UserDao { //User queries @Insert void insert(User userUi); @Query("SELECT * FROM user") LiveData<List<User>> getUserList(); @Query("SELECT DISTINCT user_id FROM user") LiveData<List<Long>> getIds(); @Query("SELECT DISTINCT agency_id FROM user") LiveData<List<String>> getAgencyIds(); @Query("SELECT DISTINCT user_id FROM user") LiveData<List<String>> getUserIds(); @Query("SELECT DISTINCT user_name FROM user") LiveData<List<String>> getUserNames(); @Query("SELECT DISTINCT surname1 FROM user") LiveData<List<String>> getSurname1(); @Query("SELECT DISTINCT surname2 FROM user") LiveData<List<String>> getSurname2(); @Query("SELECT create_date FROM user WHERE user_id =:user_id") LiveData<String> getCreatedDateByUserId(String user_id); @Query("SELECT COUNT(*) FROM user WHERE agency_id=:agency_id") LiveData<Integer> getCountByAgencyId(int agency_id); //UserAuth queries @Insert void insertAuth(UserAuth userAuth); @Query("SELECT user_id FROM userAuth") LiveData<List<String>> getUsersAuthIds(); @Query("SELECT login FROM userAuth WHERE user_id=:user_id") LiveData<String> getLoginByUserId(String user_id); @Query("SELECT password FROM userAuth WHERE user_id=:user_id") LiveData<String> getPasswordByUserId(String user_id); @Query("SELECT authentication_group_id FROM userAuth WHERE user_id=:user_id") LiveData<String> getAuthenticationGroupIdByUserId(String user_id); @Query("SELECT auhentication_type_id FROM userAuth WHERE user_id=:user_id") LiveData<String> getAuthenticationTypeIdBuUserId(String user_id); }
已尝试以下解决方案但无效:
- 初始化实体类属性
- 修正getter和setter使其与实体类属性名称匹配
- 为实体类添加空构造函数
代码中未使用@Ignore注解,请问遗漏了什么?该如何解决这个报错?
解决方案
核心问题分析
- User类字段访问权限不统一:大部分字段为
private,但surname2、surname1、user_name为public,Room注解处理器无法识别这种混合权限的字段与构造函数的匹配关系。 - UserAuth类存在拼写错误+构造函数位置问题:
authentication_type_id对应的@ColumnInfo名称拼写错误(少了一个t,写成auhentication_type_id);- 构造函数写在字段定义之前,Room无法正确关联构造函数参数与后续字段。
- DAO查询的类型不匹配:部分查询的返回类型与字段实际类型不符,触发Room校验错误,间接引发构造函数相关报错。
具体修复步骤
1. 修复User类
将三个public字段改为private,保持访问权限一致:
@ColumnInfo(name = "surname2") private String surname2 = ""; @ColumnInfo(name = "surname1") private String surname1 = ""; @ColumnInfo(name = "user_name") private String user_name = "";
2. 修复UserAuth类
- 将构造函数移到字段定义之后:
@Entity(tableName = "userAuth") public class UserAuth { // 先定义所有字段 @PrimaryKey private long user_id = 0; @ColumnInfo(name = "rowid") private String rowid = ""; @ColumnInfo(name = "authentication_group_id") private long authentication_group_id = 0; @ColumnInfo (name = "authentication_type_id") // 修正拼写错误 private long authentication_type_id = 0; @ColumnInfo(name = "login") private String login = ""; @ColumnInfo(name = "password") private String password = ""; // 再定义构造函数 public UserAuth(long user_id, String rowid, long authentication_group_id, long authentication_type_id, String login, String password) { this.user_id = user_id; this.rowid = rowid; this.authentication_group_id = authentication_group_id; this.authentication_type_id = authentication_type_id; this.login = login; this.password = password; } public UserAuth(){ } // getter/setter保持不变 }
- 修正
@ColumnInfo中的拼写错误:将auhentication_type_id改为authentication_type_id。
3. 修复DAO类的类型与拼写错误
- 修正
getIds()返回类型(User类的user_id是String类型):
@Query("SELECT DISTINCT user_id FROM user") LiveData<List<String>> getIds();
- 修正
getCountByAgencyId()参数类型(User类的agency_id是String类型):
@Query("SELECT COUNT(*) FROM user WHERE agency_id=:agency_id") LiveData<Integer> getCountByAgencyId(String agency_id);
- 修正UserAuth查询的拼写错误和类型:
@Query("SELECT authentication_type_id FROM userAuth WHERE user_id=:user_id") LiveData<Long> getAuthenticationTypeIdByUserId(String user_id);
(注意返回类型改为Long,因为字段是long类型;同时修正方法名拼写Bu为By)
4. 清理缓存重新编译
执行Build -> Clean Project和Build -> Rebuild Project,清除注解处理器缓存,确保修改生效。
内容的提问来源于stack exchange,提问作者Manuel Lucas
相关产品推荐
相关产品推荐

