Android Persistence room: Cannot figure out how to read this field from a cursor
Document is really confusing. Try with just below classes:
1) User Entity:
@Entity
public class User {
@PrimaryKey
public int id; // User id
}
2) Pet Entity:
@Entity
public class Pet {
@PrimaryKey
public int id; // Pet id
public int userId; // User id
public String name;
}
3) UserWithPets POJO:
// Note: No annotation required at this class definition.
public class UserWithPets {
@Embedded
public User user;
@Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class)
public List<Pet> pets; // or use simply 'List pets;'
/* Alternatively you can use projection to fetch a specific column (i.e. only name of the pets) from related Pet table. You can uncomment and try below;
@Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class, projection = "name")
public List<String> pets;
*/
}
parentColumn
refers to EmbeddedUser
table'sid
column,entityColumn
refers toPet
table'suserId
(User
-Pet
relation) column,entity
refers to table(Pet
) which has relation withUser
table.
4) UserDao Dao:
@Dao
public interface UserDao {
@Query("SELECT * FROM User")
public List<UserWithPets> loadUsersWithPets();
}
Now try loadUsersWithPets()
, which returns the users with their list of pets.
Edit: See my other answer for many ot many relation.
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/TypeConverter issue while retriving list of objects
The issue was I was saving data in the wrong entity, wrong TypeConverters and as a result, I was using the wrong Entity class at the time of database creation.
Here are the necessary changes I had to make to store the list of objects:
Flickr data class
@Entity(tableName = "FlickerImage")
data class FlickrImage(
@PrimaryKey(autoGenerate = true)
val id: Int,
val title: String,
@TypeConverters(MediaConverter::class)
val media: Media)
TypeConvertors for Media class
class MediaConverter {
@TypeConverter
fun fromMediaToJson(stat: Media): String {
return Gson().toJson(stat)
}
/**
* Convert a json to a list of Images
*/
@TypeConverter
fun fromJsonToMedia(jsonImages: String): Media {
val type = object : TypeToken<Media>() {}.type
return Gson().fromJson<Media>(jsonImages, type)
}
}
DAO class
@Dao
interface ImagesDao {
@Query("select * from FlickerImage")
fun getImages(): LiveData<List<FlickrImage>>
Database class
@Database(entities = [FlickrImage::class], version = 1, exportSchema = false)
@TypeConverters(MediaConverter::class)
abstract class FlickrDatabase: RoomDatabase() {
abstract val imagesDao: ImagesDao
}
private lateinit var INSTANCE: FlickrDatabase
fun getDatabase(context: Context): FlickrDatabase{
synchronized(FlickrDatabase::class.java){
if(!::INSTANCE.isInitialized){
INSTANCE = Room.databaseBuilder(context,
FlickrDatabase::class.java,
"flickerImages").build()
}
}
return INSTANCE
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(images: List<FlickrImage>)
}
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.
Related Topics
Stopping an Android App from Console
How to Change Background Color in Android App
Version Conflict Updating to 8.4.0
How to Set Android_Sdk_Home Environment Variable
Detect Touch Event on a View When Dragged Over from Other View
Replace Default Android Maps API V2 Change Mylocation Icon
How to Change the Color of a Switchcompat from Appcompat Library
Differencebetween Background, Backgroundtint, Backgroundtintmode Attributes in Android Layout Xml
Android:Inapp Purchase Receipt Validation Google Play
Programmatically Change Input Type of the Edittext from Password to Normal & Vice Versa
Is 'Shouldoverrideurlloading' Really Deprecated? What How to Use Instead
Is There a Simple Example of the Popupwindow Class Using Android V2.0
Start Activity Inside Onreceive Broadcastreceiver
Problems with Gridview Inside Scrollview in Android
Answer Incoming Call Using Android.Telecom and Incallservice