1

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

diwasip777
  • 15
  • 4

1 Answers1

0

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);
}
  • note that the 3rd output column has been commented out in the first to supress the warning issued in the build.
  • the getAsMyEntity method will return a MyEntity from the MyClassWithBool

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

MikeT
  • 51,415
  • 16
  • 49
  • 68
  • Thank you, it's sad that this is not directly possible with a class annotated with `@Entity`, but i'm gonna try and make it work using an additional class extending `MyEntity` – diwasip777 Apr 05 '23 at 09:32