I have two entities with a foreign key relation: product
and category
.
@Entity(primaryKeys = "id")
public class Product {
public final long id;
@NonNull
public final String name;
@ForeignKey(entity = Category.class, parentColumns = "id", childColumns = "categoryId")
public final long categoryId;
public Product(long id, @NonNull String name, long categoryId) {
this.id = id;
this.name = name;
this.categoryId = categoryId;
}
}
@Entity(primaryKeys = "id")
public class Category {
public final long id;
@NonNull
public final String name;
public Category(long id, @NonNull String name) {
this.id = id;
this.name = name;
}
}
I want to select all fields for both entities. I've defined a separate entity for it, with @Embedded
annotation:
public class ProductWithCategory {
@NonNull
@Embedded(prefix = "product_")
public final Product product;
@NonNull
@Embedded(prefix = "category_")
public final Category category;
public ProductWithCategory(@NonNull Product product, @NonNull Category category) {
this.product = product;
this.category = category;
}
}
Now I can create a query like this:
@Query("SELECT product.id as product_id, product.name as product_name, product.categoryId as product_categoryId, category.id as category_id, category.name as category_name FROM product JOIN category on categoryId = category.id WHERE product.id = :id")
LiveData<ProductWithCategory> getProduct(long id);
The problem is that I have to manually specify all fields which becomes too verbose if I have entities with 5 - 10 fields. Is it possible to use some wildcard approach without manually specifying all fields?
Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. In case of SQLite, There is no compile time verification of raw SQLite queries. But in Room there is SQL validation at compile time.
room. Embedded instead. Can be used as an annotation on a field of an Entity or Pojo to signal that nested fields (i.e. fields of the annotated field's class) can be referenced directly in the SQL queries. If the container is an Entity , these sub fields will be columns in the Entity 's database table.
A Room entity includes fields for each column in the corresponding table in the database, including one or more columns that comprise the primary key.
Finally I used @Relation
annotation to solve this. The only disadvantage is that I have to use either List
or Set
for it, even if in this case it's either 0 or 1 entity:
public class ProductWithCategory {
@NonNull
@Embedded
public final Product product;
@Relation(parentColumn = "categoryId", entityColumn = "id", entity = Category.class)
public List<Category> category;
public ProductWithCategory(@NonNull Product product) {
this.product = product;
}
}
But that simplifies the query:
@Query("SELECT * FROM product WHERE product.id = :id")
LiveData<ProductWithCategory> getProduct(long id);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With