Android Room Persistent Library - Typeconverter Error of Error: Cannot Figure Out How to Save Field to Database"

Android room persistent library - TypeConverter error of error: Cannot figure out how to save field to database

This is a common problem I've seen since Room was announced. Room does not support the ability to store Lists directly, nor the ability to convert to/from Lists. It supports converting and storing POJO's.

In this case the solution is simple. Instead of storing a List<CountryLang> you want to store CountryLangs (note the 's')

I've done a quick example of a solution here :

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

This POJO is an inversion of your previous object. It is an object that stores a list of languages. Instead of a list of objects that store your language.

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

This converter takes a list of strings and converts them into a comma seperated string to be stored in a single column. When it fetches the string from the SQLite db to convert back, it splits the list on commas, and populates the CountryLangs.

Insure to update your RoomDatabase version after making these changes.You have the rest of the configuration correct. Happy hunting with the rest of your Room persistence work.

Android Room - error: Cannot figure out how to save this field into database

Date is exactly the example given in https://developer.android.com/training/data-storage/room/referencing-data.

For example, if we want to persist instances of Date, we can write the following TypeConverter to store the equivalent Unix timestamp in the database:

public class Converters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}

The preceding example defines 2 functions, one that converts a Date object to a Long object and another that performs the inverse conversion, from Long to Date. Since Room already knows how to persist Long objects, it can use this converter to persist values of type Date.

Next, you add the @TypeConverters annotation to the AppDatabase class so that Room can use the converter that you've defined for each entity and DAO in that AppDatabase:

AppDatabase.java

@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}

A side note: java.util.Date is considered to be badly designed (and java.util.Calendar is much worse). If you have any non-trivial date-time logic and can get away with API level 26 (Java 8 on desktop), it's generally better to use java.time package. And if you can't, see https://github.com/JakeWharton/ThreeTenABP for a backport.

Kotlin Room Error Cannot figure out how to save this field into database With TypeConverters

I'm going to have to disagree with the answer from @DivijGupta, you can put the @TypeConverters annotation on entity fields and it will limit the scope of the converter to that particular field as I am sure you intended. The documentation here actually lists the usage as:

If you put it on an Entity field, only that field will be able to use it.

The error is actually to do with how Kotlin translates the annotations into Java bytecode. If you have a look at what adding an annotation to a field actually does in the decompiled code, you can see that Kotlin places it on the constructor parameter, not the field itself. Therefore as Room doesn't see an annotation on the field it gives you the error.

To fix this you have to use an extra field qualifier when annotating, in this instance:

@field:TypeConverters(FrequencyTypeConverter::class)

and you can read more about this in the Kotlin documentation on Annotation use-site targets.


Just as a side note, the answer from @DivijGupta would fix the error as the problem that I have outlined wouldn't exist, but it is just a workaround.

Room error - Cannot figure out how to save this field into database. You can consider adding a type converter for it.

You cant use entities inside other entities (e.g. Film in Reservation). You should either use "relationships between entities" or try "Embedded" annotation.
Reffer to this link for more info.

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it. in my app?

The typeConvertor seems to be a bit off. Instead of object let it be a class. Store in DB as JSON string and retrieve it ( GSON library optional).

class SourceTypeConverter {
@TypeConverter
fun fromSource(source: Source): String {
return JSONObject().apply {
put("id", source.id)
put("name", source.name)
}.toString()
}

@TypeConverter
fun toSource(source: String): Source {
val json = JSONObject(source)
return Source(json.get("id"), json.getString("name"))
}
}

Now register this TypeConvertor to the Database with annotation TypeConverter.

@Database(entities = [Article::class], version = 1, exportSchema = false)
@TypeConverters(SourceTypeConverter::class)
abstract class SportNewsDatabase : RoomDatabase() {
/* your code here */
}

Cannot figure out how to save this field into database. I have written data class,dao and typeconverters, but still unable to detect error

I think your DataTypeConverter is wrong you can try change like this :

class DataTypeConverter{

var gson = Gson()

@TypeConverter
fun stringToUserList(data: String?): List<User?>? {
if (data == null) {
return Collections.emptyList()
}
val listType: Type =
object : TypeToken<List<User?>?>() {}.type
return gson.fromJson<List<User?>>(data, listType)
}

@TypeConverter
fun userDetailListToString(someObjects: List<User?>?): String? {
return gson.toJson(someObjects)
}
}

Don't forget to add @TypeConverters(DataTypeConverter::class) to @Database



Related Topics



Leave a reply



Submit