Android Room library - select all fields for embedded entities
Asked Answered
S

1

7

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?

Spherical answered 3/1, 2018 at 13:33 Comment(0)
S
9

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);
Spherical answered 13/1, 2018 at 11:43 Comment(1)
Thanks for this answer, helped me out. In my case to avoid having to deal with a list each time you access the object (category in this case) I also created a method that just returns the first object (category) in the list like this answer: https://mcmap.net/q/808775/-room-database-with-one-to-one-relation It still isn't as tidy as I'd like as the list (category) has to be public unfortunatelySabah

© 2022 - 2024 — McMap. All rights reserved.