I have an entity looking as follows:
@Entity(tableName = "my_table")
public class MyEntity {
@PrimaryKey(autoGenerate = true)
@ColumnInfo
private final Integer id;
@ColumnInfo
private final String data;
@Ignore
private final boolean bool;
public MyEntity(Integer id, String data) {
this.id = id;
this.data = data;
this.bool= false;
}
public MyEntity(Integer id, String data, boolean bool) {
this.id = id;
this.data = data;
this.bool = bool;
}
// getters...
}
And the corresponding DAO:
@Dao
public interface MyDao {
@Query("SELECT id, data, 1 FROM my_table WHERE id = :id")
LiveData<MyEntity> getById(int id);
}
When i call getById(int)
, only the first constructor without bool
is being used and the returned MyEntity
always has bool = false
. It seems like the 1
in the query is completely ignored.
How can i make it so the DAO uses the other constructor which includes bool
(and therefore sets bool = true
)?
It seems like the 1 in the query is completely ignored.
And that is what you have specified. As far as Room is concerned the bool column is superfluous and will be ignored if building a MyEntity. Hence the warning like:-
warning: The query returns some columns [bool] which are not used by MyEntity. You can use @ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with @RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns. You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: id, data, bool.
LiveData<MyEntity> getById(int id);
Now if you were to have a POJO, for example:-
class MyClassWithBool {
Integer id;
String data;
boolean bool;
public String getData() {
return data;
}
public Integer getId() {
return id;
}
public boolean isBool() {
return bool;
}
public MyEntity getAsMyEntity() {
return new MyEntity(id,data,bool);
}
}
Then room will be able to assign the additional column BUT only if you return the POJO. e.g. you could then have:-
@Dao
public interface MyDao {
@Query("SELECT id, data/*, 1*/ FROM my_table WHERE id = :id")
LiveData<MyEntity> getById(int id);
@Query("SELECT id, data, 1 AS bool FROM my_table WHERE id=:id")
LiveData<MyClassWithBool> getByIdWithBool(int id);
}
getAsMyEntity
method will return a MyEntity from the MyClassWithBoolThe assumption is that the far simpler:-
public MyEntity(Integer id, String data) {
this.id = id;
this.data = data;
this.bool= true;
}
would not suit (in which the 3rd column is also superfluous)
In short, if you want anything other than the Entity extracted, then you need to specify a suitable class (or type in the case of a single value) rathe than the Entity class.
Furthermore Room expects the name of the output columns to match the member names (except in the case of a single value when it only has a 1-1 mapping between column and where to place the value). Hence the use of AS
to give the column a name.