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

如何解决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注解,请问遗漏了什么?该如何解决这个报错?


解决方案

核心问题分析

  1. User类字段访问权限不统一:大部分字段为private,但surname2、surname1、user_name为public,Room注解处理器无法识别这种混合权限的字段与构造函数的匹配关系。
  2. UserAuth类存在拼写错误+构造函数位置问题:
    • authentication_type_id对应的@ColumnInfo名称拼写错误(少了一个t,写成auhentication_type_id);
    • 构造函数写在字段定义之前,Room无法正确关联构造函数参数与后续字段。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:55:04