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).
誰かが私を助けてくれませんか?
前もって感謝します :)
わかりました、どこが私の間違いだったのかわかりました。私の@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)を挿入し、その後に関係にあるすべてのデータを挿入する必要があることです。