Androidルーム永続ライブラリ モデルオブジェクト全体を別のリストを持つテーブルに挿入する方法。
私の意味をお見せしましょう:
@Entity(tableName = TABLE_NAME)
public class CountryModel {
public static final String TABLE_NAME = "Countries";
@PrimaryKey
private int idCountry;
private List<CountryLang> countryLang = null;
public int getIdCountry() {
return idCountry;
}
public void setIdCountry(int idCountry) {
this.idCountry = idCountry;
}
public String getIsoCode() {
return isoCode;
}
public void setIsoCode(String isoCode) {
this.isoCode = isoCode;
}
/**
here i am providing a list of coutry information how to insert
this into db along with CountryModel at same time
**/
public List<CountryLang> getCountryLang() {
return countryLang;
}
public void setCountryLang(List<CountryLang> countryLang) {
this.countryLang = countryLang;
}
}
私のDAOは次のようになります:
@Dao
public interface CountriesDao{
@Query("SELECT * FROM " + CountryModel.TABLE_NAME +" WHERE isoCode =:iso_code LIMIT 1")
LiveData<List<CountryModel>> getCountry(String iso_code);
@Query("SELECT * FROM " + CountryModel.TABLE_NAME )
LiveData<List<CountryModel>> getAllCountriesInfo();
@Insert(onConflict = REPLACE)
Long[] addCountries(List<CountryModel> countryModel);
@Delete
void deleteCountry(CountryModel... countryModel);
@Update(onConflict = REPLACE)
void updateEvent(CountryModel... countryModel);
}
database.CountriesDao().addCountries(countryModel);
を呼び出すと、次の部屋dbコンパイルエラーが表示されます。Error:(58、31)エラー:このフィールドをデータベースに保存する方法がわかりません。タイプコンバーターを追加することを検討できます。
countryLangという別のテーブルが必要ですか?もしそうなら、挿入ステートメントでそれらを接続するための部屋を指示する方法は?
CountryLangオブジェクト自体は次のようになります。
public class CountryLang {
private int idCountry;
private int idLang;
private String name;
public int getIdCountry() {
return idCountry;
}
public void setIdCountry(int idCountry) {
this.idCountry = idCountry;
}
public int getIdLang() {
return idLang;
}
public void setIdLang(int idLang) {
this.idLang = idLang;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
応答は次のようになります。
"country_lang": [
{
"id_country": 2,
"id_lang": 1,
"name": "Austria"
}
]
すべての国のため、ここでは1つ以上のアイテムになりません。 country_langリスト内の1つのアイテムのみを指定するのは快適です。したがって、country_langのテーブルを作成してから、CountryModelにリンクする方法をいくつか作成できます。しかし、どのように?外部キーを使用できますか?フラットファイルを使用する必要がないことを望んでいました。だからあなたのことをjsonとして保存する必要がありますか?一時的なスペースを使用しないことをお勧めしますか?代わりに何を使用しますか?
Omkarが言ったように、できません。ここでは、ドキュメントに従って常に@Ignore
アノテーションを使用する理由を説明します。 https://developer.Android.com/training/data-storage/room/referencing-data.html#understand-オブジェクト参照なし
テーブルのCountryオブジェクトを処理して、その能力のデータのみを取得します。 Languagesオブジェクトは別のテーブルに移動しますが、同じDaoを保持できます。
TypeConverterおよびGSONを使用して、リストオブジェクトフィールドを持つクラスを簡単に挿入できます。
public class DataConverter {
@TypeConverter
public String fromCountryLangList(List<CountryLang> countryLang) {
if (countryLang == null) {
return (null);
}
Gson gson = new Gson();
Type type = new TypeToken<List<CountryLang>>() {}.getType();
String json = gson.toJson(countryLang, type);
return json;
}
@TypeConverter
public List<CountryLang> toCountryLangList(String countryLangString) {
if (countryLangString == null) {
return (null);
}
Gson gson = new Gson();
Type type = new TypeToken<List<CountryLang>>() {}.getType();
List<CountryLang> countryLangList = gson.fromJson(countryLangString, type);
return countryLangList;
}
}
リストオブジェクトフィールドの前に@TypeConverters
注釈を追加し、
@Entity(tableName = TABLE_NAME)
public class CountryModel {
//....
@TypeConverters(DataConverter.class)
public List<CountryLang> getCountryLang() {
return countryLang;
}
//....
}
TypeConverters in Roomの詳細については、ブログ here および official docs をご覧ください。
コピーペーストを楽しむ怠け者のGoogle社員向けのKotlinにあるAman Guptaのコンバーターは次のとおりです。
class DataConverter {
@TypeConverter
fun fromCountryLangList(value: List<CountryLang>): String {
val gson = Gson()
val type = object : TypeToken<List<CountryLang>>() {}.type
return gson.toJson(value, type)
}
@TypeConverter
fun toCountryLangList(value: String): List<CountryLang> {
val gson = Gson()
val type = object : TypeToken<List<CountryLang>>() {}.type
return gson.fromJson(value, type)
}
}
できません。
これを達成する唯一の方法は、 @ ForeignKey 制約を使用することです。親POJO内にオブジェクトのリストを保持したい場合は、 @ Ignore を使用するか、 @ TypeConverter を指定する必要があります
詳細については、このブログの投稿に従ってください:
https://www.bignerdranch.com/blog/room-data-storage-for-everyone/
およびサンプルコード:-
https://github.com/googlesamples/Android-architecture-components
カスタムオブジェクトフィールドに@Embeddedを追加します(次の例を参照)
//this class refers to pojo which need to be stored
@Entity(tableName = "event_listing")
public class EventListingEntity implements Parcelable {
@Embedded // <<<< This is very Important in case of custom obj
@TypeConverters(Converters.class)
@SerializedName("mapped")
public ArrayList<MappedItem> mapped;
//provide getter and setters
//there should not the duplicate field names
}
//add converter so that we can store the custom object in ROOM database
public class Converters {
//room will automatically convert custom obj into string and store in DB
@TypeConverter
public static String
convertMapArr(ArrayList<EventListingEntity.MappedItem> list) {
Gson gson = new Gson();
String json = gson.toJson(list);
return json;
}
//At the time of fetching records room will automatically convert string to
// respective obj
@TypeConverter
public static ArrayList<EventsListingResponse.MappedItem>
toMappedItem(String value) {
Type listType = new
TypeToken<ArrayList<EventsListingResponse.MappedItem>>() {
}.getType();
return new Gson().fromJson(value, listType);
}
}
//Final db class
@Database(entities = {EventsListingResponse.class}, version = 2)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
....
}