Search code examples
javaandroidandroid-room

Problem when try to build Room Database rising so many errors


I was developing some simple app, which make use of Room library to create a database to keep info regarding an User model class.

My problem is I'm getting several error when I try to build the database like the following:

error: Entity class must be annotated with @Entity

error: 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).

error: An entity must have at least 1 field annotated with @PrimaryKey

error: [SQLITE_ERROR] SQL error or missing database (near ")": syntax error)

error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such table: userUi)

Regarding my class are this:

UserDao.java

@Dao
public interface UserDao {

    @Insert
    void insert(User userUi);

    @Query("SELECT DISTINCT id FROM userUi")
    List<Byte> getIds();

    @Query("SELECT DISTINCT agency_id FROM userUi")
    List<String> getAgencyIds();

    @Query("SELECT DISTINCT user_id FROM userUi")
    List<String> getUserIds();

    @Query("SELECT DISTINCT user_code FROM userUi")
    List<String> getUserCodes();

    @Query("SELECT DISTINCT user_name FROM userUi")
    List<String> getUserNames();

    @Query("SELECT DISTINCT profile FROM userUi")
    List<String> getProfiles();

    @Query("SELECT COUNT(*) FROM userUi WHERE agency_id=:agency_id")
    Integer getCountByAgencyId(int agency_id);

}

User.java


@Entity(tableName = "userUi", indices = {@Index(value = {"user_code"})})
public class User {
    @PrimaryKey(autoGenerate = true)
    private String id;

    @ColumnInfo(name="agency_id")
    private String agency_id;

    @ColumnInfo(name="user_id")
    private String user_id;

    @PrimaryKey(autoGenerate = true)
    private String user_code;

    @ColumnInfo(name="password")
    private String password;

    @ColumnInfo(name="csc_authenticable")
    private String csc_authenticable;

    @ColumnInfo(name="equipment_type")
    private String equipment_type;

    @ColumnInfo(name = "equipment_subtype")
    public String equipment_subtype;

    @ColumnInfo(name = "profile")
    public String profile;

    @ColumnInfo(name = "user_name")
    public String user_name;

    public User(String id, String agency_id, String user_code, String password, String csc_authenticable, String equipment_type, String equipment_subtype, String profile, String user_name) {
        this.id = id;
        this.agency_id = agency_id;
        this.user_code = user_code;
        this.password = password;
        this.csc_authenticable = csc_authenticable;
        this.equipment_type = equipment_type;
        this.equipment_subtype=equipment_subtype;
        this.profile = profile;
        this.user_name = user_name;
    }

    public String getId() {
        return id;
    }

    public String getAgency_id() {
        return agency_id;
    }

    public String getUser_id() {
        return user_id;
    }

    public String getUser_code() {
        return user_code;
    }

    public String getPassword() {
        return password;
    }

    public String getCsc_authenticable() {
        return csc_authenticable;
    }

    public String getEquipment_type() {
        return equipment_type;
    }

    public String getEquipment_subtype() {
        return equipment_subtype;
    }

    public String getProfile() {
        return profile;
    }

    public String getUser_name() {
        return user_name;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setAgency_id(String agency_id) {
        this.agency_id = agency_id;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }

    public void setUser_code(String user_code) {
        this.user_code = user_code;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setCsc_authenticable(String csc_authenticable) {
        this.csc_authenticable = csc_authenticable;
    }

    public void setEquipment_type(String equipment_type) {
        this.equipment_type = equipment_type;
    }

    public void setEquipment_subtype(String equipment_subtype) {
        this.equipment_subtype = equipment_subtype;
    }

    public void setProfile(String profile) {
        this.profile = profile;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }
}

Database.java


@androidx.room.Database(
        entities = {
                UserDao.class
        },
        version = 6
)

@TypeConverters({DateConverter.class})
public abstract class Database extends RoomDatabase {

    public static Database buildDataBase(final Context context){
        return Room.databaseBuilder(
                context,
                Database.class,
                AppConstant.DB_NAME)
                .allowMainThreadQueries().setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
                .fallbackToDestructiveMigration().build();
    }

    public abstract UserDao userUiContractDaoDAO();


}

So, I don't know what it's rising so many errors, but if you can see something I'm missing or doing wrong, take thanks in advance !


Solution

  • Issue 1

    The issue causing must be annotated with @Entity is because you are specifying UserDao as a table in the list of entities. So instead of:-

    entities = {
                    UserDao.class
            }
    

    Use :-

    entities = {
                    User.class
            }
    

    i.e. the entity not the dao.

    Issue 2

    The next issue is that you have specified multiple Primary keys, there can only be 1.

    error: You cannot have multiple primary keys defined in an Entity. If you want to declare a composite primary key, you should use @Entity#primaryKeys and not use @PrimaryKey. Defined Primary Keys: PrimaryKey[id], PrimaryKey[user_code]
    

    So perhaps :-

    //@PrimaryKey(autoGenerate = true) /*,<<<<<<<< COMMENTED OUT can't have 2 primary keys*/
    private String user_code;
    
    • i.e. comment out the second primary key.

    Issue 3

    You will then get

    error: If a primary key is annotated with autoGenerate, its type must be int, Integer, long or Long.
    

    So perhaps;-

    @PrimaryKey/*(autoGenerate = true)*/
    private String id;
    

    Issue 4

    Then :-

    error: You must annotate primary keys with @NonNull. "id" is nullable. SQLite considers this a bug and Room does not allow it. See SQLite docs for details: https://www.sqlite.org/lang_createtable.html
    private String id;
    

    :-

    @NonNull
    @PrimaryKey/*(autoGenerate = true)*/
    private String id;
    

    Issue 5

    Next you will get:-

    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).
    

    This is because none of the constructors handles the expectation of building a Byte from a String as per:-

    @Query("SELECT DISTINCT id FROM userUi")
    List<Byte> getIds();
    

    Use :-

    @Query("SELECT DISTINCT id FROM userUi")
    List<String> getIds();
    

    And then the project will compile successfully.

    If you want user_code to be unique then you can use:-

    @Entity(tableName = "userUi", indices = {@Index(value = {"user_code"}, unique = true)})