Room composite Primary Key link to Foreign Key

2020-06-16 04:15发布

问题:

I am implementing an android application with Room database and have a small question about relationships in this DB.

I have two tables:

@Entity(tableName = "foods", primaryKeys = {"id", "language_id"},
        indices = {@Index(value = {"id", "language_id"}, unique = true)},
        inheritSuperIndices = true)
public class Food {

    @NonNull
    @ColumnInfo(name = "id")
    private String mId;

    @NonNull
    @ColumnInfo(name = "language_id")
    private String mLanguageId;

}

@Entity(tableName = "ingredients", primaryKeys = {"id", "language_id"},
        indices = {@Index(value = {"id", "language_id"}, unique = true), 
        @Index(value = {"food_id", "food_language_id"}, unique = true)},
        foreignKeys = {@ForeignKey(entity = Food.class, parentColumns ="id", 
        childColumns = "food_id", onUpdate = CASCADE, onDelete = CASCADE),
        @ForeignKey(entity = Food.class, parentColumns = "language_id", 
        childColumns = "food_language_id", onUpdate = CASCADE, onDelete = 
        CASCADE)},
        inheritSuperIndices = true)
public class Ingredient {

    @NonNull
    @ColumnInfo(name = "id")
    private String mId;

    @NonNull
    @ColumnInfo(name = "language_id")
    private String mLanguageId;

    @ColumnInfo(name = "food_id")
    private String mFoodId;

    @ColumnInfo(name = "food_language_id")
    private String mFoodLanguageId;

}

The both tables 'Food' and 'Ingredient' have composite primary keys ('id', 'language_id'). The Food object has to contains a List and of course a @Relationship

public class FoodWithIngredients extends Food{

    @Relation(parentColumn = "id", entityColumn = "food_id", entity = 
    Ingredient.class)
    private List<Ingredient> mIngredients;

}

After I try to run this code received these messages

Warnning:

food_language_id column references a foreign key but it is not part of an index. This may trigger full table scans whenever parent table is modified so you are highly advised to create an index that covers this column.

Error:

Ingredient has a foreign key (food_id) that references Food (id) but Food does not have a unique index on those columns nor the columns are its primary key. SQLite requires having a unique constraint on referenced parent columns so you must add a unique index to Food that has (id) column(s).

Could someone help me with that?

Thanks in advance :)

回答1:

Ok, I found where was my mistake. My @ForeignKey was wrong, the right one is this:

@ForeignKey(
             entity = Food.class,
             parentColumns = {"id", "language_id"},
             childColumns = {"food_id", "food_language_id"},
             onUpdate = CASCADE, onDelete = CASCADE)

The difference is that I put multiple columns inside 'parentColumns' and 'childColumns' and it works correct.

@Danail Alexiev The insertion is something like this:

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertFoods(List<Food> foods);

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertIngredients(List<Ingredient> ingredients);

@Transaction
public void insertFoodData(List<Food> foods, RulesOfGolfDatabase database) {
    if (foods != null && database != null) {
        insertFoods(foods);
        for (Food food : foods) {
            insertIngredients(food.getIngrediants());
        }
    }
}

The most important thing here is that you have to insert first the owner of the @Relation (In this example is Food) and after that every data which is in the relationship