Android room persistent library-TypeConverter ошибка ошибки: не удается выяснить, как сохранить поле в базе данных"

Im не удалось создать typeConverter в комнате из-за ошибки. Кажется, я следую всем документам. Я хотел бы преобразовать список в строку json. давайте взглянем на мою сущность:

      @Entity(tableName = TABLE_NAME)
public class CountryModel {

    public static final String TABLE_NAME = "Countries";

    @PrimaryKey
    private int idCountry;
/* I WANT TO CONVERT THIS LIST TO A JSON STRING */
    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;
    }

    public List<CountryLang> getCountryLang() {
        return countryLang;
    }

    public void setCountryLang(List<CountryLang> countryLang) {
        this.countryLang = countryLang;
    }

}

на country_lang это то, что я хотел бы преобразовать в JSON-строку. Поэтому я создал следующий конвертер: Конвертеры.java:

public class Converters {

@TypeConverter
public static String countryLangToJson(List<CountryLang> list) {

    if(list == null)
        return null;

        CountryLang lang = list.get(0);

    return list.isEmpty() ? null : new Gson().toJson(lang);
}}

тогда проблема в том, куда я помещаю @TypeConverters ({Converters.class}) я продолжаю получать ошибку. Но официально именно здесь я разместил аннотацию, чтобы зарегистрировать typeConverter:

@Database(entities = {CountryModel.class}, version = 1 ,exportSchema = false)
@TypeConverters({Converters.class})
public abstract class MYDatabase extends RoomDatabase {
    public abstract CountriesDao countriesDao();
}

ошибки я получаю это:

Error:(58, 31) error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.

5 ответов


это общая проблема, которую я видел, так как номер был объявлен. Комната не поддерживает возможность хранить списки напрямую, ни возможность конвертировать в / из списков. Он поддерживает преобразование и сохранение в POJO-объект.

в этом случае решение простое. Вместо хранения List<CountryLang> вы хотите сохранить CountryLangs (обратите внимание на "s")

Я сделал быстрый пример решения здесь :

public class CountryLangs {
    private List<String> countryLangs;

    public CountryLangs(List<String> countryLangs) {
        this.countryLangs = countryLangs;
    }

    public List<String> getCountryLangs() {
        return countryLangs;
    }

    public void setCountryLangs(List<String> countryLangs) {
        this.countryLangs = countryLangs;
    }
}

этот POJO является инверсией вашего предыдущего объекта. Это объект, хранящий список языков. Вместо списка объектов, хранящих ваш язык.

public class LanguageConverter {
    @TypeConverter
    public CountryLangs storedStringToLanguages(String value) {
        List<String> langs = Arrays.asList(value.split("\s*,\s*"));
        return new CountryLangs(langs);
    }

    @TypeConverter
    public String languagesToStoredString(CountryLangs cl) {
        String value = "";

        for (String lang :cl.getCountryLangs())
            value += lang + ",";

        return value;
    }
}

этот конвертер берет список строк и преобразует их в запятую отдельную строку, которая будет храниться в одном столбце. Когда он извлекает строку из БД SQLite для преобразования обратно, он разбивает список на запятые и заполняет CountryLangs.

застраховать, чтобы обновить версию RoomDatabase после внесения этих изменений.У вас есть остальная часть конфигурации правильный. Счастливой охоты с остальной частью вашей работы настойчивости комнаты.


была такая же ошибка: "не могу понять, как сохранить это поле в базе данных" при попытке добавить поле Дата. Пришлось добавить класс конвертера для него и добавить аннотацию @TypeConverters в поле.

пример:

WordEntity.java

import android.arch.persistence.room.TypeConverters;

    @Entity
    public class WordEntity {

        @PrimaryKey(autoGenerate = true)
        public int id;
        private String name;
        @TypeConverters(DateConverter.class)
        private Date createDate;

класс dateconverter.java:

import android.arch.persistence.room.TypeConverter;

import java.util.Date;

public class DateConverter {

    @TypeConverter
    public static Date toDate(Long timestamp) {
        return timestamp == null ? null : new Date(timestamp);
    }

    @TypeConverter
    public static Long toTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

@TypeConverter не признает List класс, поэтому вы должны использовать ArrayList вместо этого, поэтому вам не нужна дополнительная оболочка для списка, который вы хотите сохранить.


вы также должны создать этот TypeConverter который преобразует ваш List to String,

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

и для получения дополнительной информации вы также можете проверить мой другой ответ.


пример Котлина (не хороший, но простой, TODO: json):

import android.arch.persistence.room.*

@Entity(tableName = "doctor")
data class DoctorEntity(

    @PrimaryKey
    @ColumnInfo(name = "id") val id: Long,

    @ColumnInfo(name = "contactName") val contactName: String?,

    @TypeConverters(CategoryConverter::class)
    @ColumnInfo(name = "categories") val categories: Categories?,

    @TypeConverters(CategoryConverter::class)
    @ColumnInfo(name = "languages") val languages: Categories?
) 

data class Categories(
    val categories: ArrayList<Long> = ArrayList()
)

class CategoryConverter {

    @TypeConverter
    fun toCategories(value: String?): Categories {
        if (value == null || value.isEmpty()) {
            return Categories()
        }

        val list: List<String> = value.split(",")
        val longList = ArrayList<Long>()
        for (item in list) {
            if (!item.isEmpty()) {
                longList.add(item.toLong())
            }
        }
        return Categories(longList)
    }

    @TypeConverter
    fun toString(categories: Categories?): String {

        var string = ""

        if (categories == null) {
            return string
        }

        categories.categories.forEach {
            string += "$it,"
        }
        return string
    }
}