web-dev-qa-db-ja.com

外部キーへのルームコンポジット主キーリンク

Android Roomデータベースを使用したアプリケーションを実装しています。このDBの関係について少し質問があります。

2つのテーブルがあります。

@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;

}

「Food」と「Ingredient」の両方のテーブルには、複合主キー(「id」、「language_id」)があります。 Foodオブジェクトには、リストと、もちろん@Relationshipが含まれている必要があります。

public class FoodWithIngredients extends Food{

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

}

このコードを実行しようとした後、これらのメッセージを受け取りました

警告:

food_language_idカラムは外部キーを参照しますが、インデックスの一部ではありません。これにより、親テーブルが変更されるたびに全テーブルスキャンがトリガーされる可能性があるため、この列をカバーするインデックスを作成することを強くお勧めします。

エラー:

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

誰かが私を助けてくれませんか?

前もって感謝します :)

8
MrVasilev

わかりました、どこが私の間違いだったのかわかりました。私の@ForeignKeyは間違っていました、正しいものはこれです:

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

違いは、「parentColumns」と「childColumns」内に複数の列を配置すると、正しく機能することです。

@Danail Alexiev挿入は次のようになります。

@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());
        }
    }
}

ここで最も重要なことは、最初に@Relationの所有者(この例ではFood)を挿入し、その後に関係にあるすべてのデータを挿入する必要があることです。

6
MrVasilev