Issue Basics
ObjectBox version 2.5.1
Reproducibility: [always]
Hi, I am getting this error everytime I want to load my Object even though on saving I checked in the debugger and see that the relation target is not null and everything is saved correctly.
I am having those trhee entity classes
#Entity
data class NetflixCache (
val results: List<NetflixSearchResult>,
#Id var objectBoxId: Long?
) {
var searchParams: ToOne<SearchParams> = ToOne<SearchParams>(this, NetflixCache_.searchParams)
}
#Entity
data class SearchParams(val genrelist: String,
val type: String,
val imdbRatingMin: String,
val countryId: String,
val startYear: Int,
val endYear: Int,
val offset: Int? = 0,
val timeStamp: Long,
#Id var id: Long? = null)
#Entity
data class NetflixSearchResult (
val vtype: String?,
val img: String?,
val nfid: Long?,
val imdbid: String?,
val title: String?,
val clist: String?,
val poster: String?,
val imdbrating: Double?,
val synopsis: String?,
val titledate: Date?,
val year: Int?,
var id: Long,
#Id var objectBoxId: Long?
)
Using this code to save:
val cacheBox = LetsFlixApplication.boxStore.boxFor(NetflixCache::class.java)
val netflixCache = NetflixCache(searchResults, null)
netflixCache.searchParams.target = searchParams
cacheBox.put(netflixCache)
And this code to load:
val cachedResult = cacheBox.all //<-Exception is thrown here
As you can see in debugger when saving, ToOne Object is NOT null:
https://ibb.co/s3tdhqP
This is the exact exception message I am getting:
ToOne object is null inside com.haenles.letsflix.domain.NetflixCache
Issue for me was that data class was missing default values as recommended in the doc:
#Entity
data class User(
#Id var id: Long = 0,
var name: String? = null
)
Related
I have two tables. First table is as below
#Entity
data class GramPanchayatSurveyEntity(
#PrimaryKey
var gpCode: Int,
var distCode: Int,
var locationTypeCode: Int,
var location: String,
var latitude: String,
var longitude: String,
var googleLocation: String,
var distanceBtwHeadQrToGp: String,
var recommendedHeightOfTower: String,
var BBNL_Exist: String,
var anyCongestion: String,
var nearByGpCode: Int,
var surveyBy: String,
var surveyAt: String,
val status :String
)
And the second table as
#Entity
data class AddedPhotoEntity (
#PrimaryKey
var photoUniqueId:Int,
var iPhotoTypeCode: Int,
var photoTypeName: String,
var sPhotoURL: String,
var gpCode: Int,
var photoStatus : String,
var rotationAngle :Float
)
I have a relation class that fetches data from both tables as
class GpSurveyWithImageRelation {
#Embedded
var gpSurveyEntity: GramPanchayatSurveyEntity? = null
#Relation(parentColumn = "gpCode", entityColumn = "gpCode")
var sPhotoArray: List<AddedPhotoEntity>? = null
}
When I am getting data from this relation and convert the data into JSON Array using gson it gives me the output like that
This is the actual output of when I convert the list (getting from the relation) into a JSON array
This is the required output.
Please anyone help me in creating the relation class between two tables so that I can got the required output.
Thanks in advance.
Your issue is that you have the var/field gpSurveyEntity Embedded as a GramPanchayatSurveyEntity object, instead you want GpSurveyWithImageRelation to be:-
data class GpSurveyWithImageRelation(
var gpCode: Int,
var distCode: Int,
var locationTypeCode: Int,
var location: String,
var latitude: String,
var longitude: String,
var googleLocation: String,
var distanceBtwHeadQrToGp: String,
var recommendedHeightOfTower: String,
var BBNL_Exist: String,
var anyCongestion: String,
var nearByGpCode: Int,
var surveyBy: String,
var surveyAt: String,
var status :String,
#Relation(entity = AddedPhotoEntity::class, parentColumn = "gpCode", entityColumn = "gpCode")
var sPhotoArray: List<AddedPhotoEntity> = emptyList()
)
in my project , I have two Data Model class
first :
#Entity(tableName = TABLE_TASK)
data class TaskEntity(
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "task_id") val taskId: Int,
#ColumnInfo(name = "task_title") val taskTitle: String?,
#ColumnInfo(name = "task_desc") val taskDesc: String?,
#ColumnInfo(name = "task_priority") val taskPriority: Int?,
#ColumnInfo(name = "task_status") val taskStatus: String?,
#ColumnInfo(name = "task_time") val taskTime: String?,
#ColumnInfo(name = "task_notify") val taskNotify: String?
)
and second :
data class SubtaskModel(
val subTasktitle : String?,
val subTaskStatus : Boolean?
)
and I wanted to add a filed in my first Data Model class as the code below (the last field ) :
#Entity(tableName = TABLE_TASK)
data class TaskEntity(
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "task_id") val taskId: Int,
#ColumnInfo(name = "task_title") val taskTitle: String?,
#ColumnInfo(name = "task_desc") val taskDesc: String?,
#ColumnInfo(name = "task_priority") val taskPriority: Int?,
#ColumnInfo(name = "task_status") val taskStatus: String?,
#ColumnInfo(name = "task_time") val taskTime: String?,
#ColumnInfo(name = "task_notify") val taskNotify: String?,
#ColumnInfo(name = "task_subtask") val taskSubTask: MutableList<SubtaskModel>?
)
the error that i have got :
Cannot figure out how to save this field into database. You can
consider adding a type converter for it.
so I read(developer.android.com) and I did search about this but I couldn't figure out how can write Type Converter.
thank you
Follow below steps :
Step1. : create a convertor class -
class MyConverter {
#TypeConverter
fun listToJson(value: List< SubtaskModel >?): String = Gson().toJson(value)
#TypeConverter
fun jsonToList(value: String) = Gson().fromJson(value, Array<SubtaskModel>::class.java).toList()
}
Step 2 -> Add converter to your dataBase class
#Database(entities = [TaskEntity::class], version = 1)
#TypeConverters(MyConverter::class)
abstract class myDataBase : RoomDatabase() {
abstract fun myDao(): MyDao
}
That's it.
Here is my entity class:
#Entity
data class User(
#PrimaryKey
#Json(name = "id") val userId: String,
#Json(name = "login") val userName: String,
#Json(name = "avatar_url") val userAvatar: String,
val profile: Profile? = null
) : Serializable
Here is my Profile data class
data class Profile(
val avatar_url: String,
val bio: String,
val blog: String,
val company: Any,
val created_at: String,
val email: Any,
val events_url: String,
val followers: Int,
val followers_url: String,
val following: Int,
val following_url: String,
val gists_url: String,
val gravatar_id: String,
val hireable: Boolean,
val html_url: String,
val id: Int,
val location: String,
val login: String,
val name: String,
val node_id: String,
val organizations_url: String,
val public_gists: Int,
val public_repos: Int,
val received_events_url: String,
val repos_url: String,
val site_admin: Boolean,
val starred_url: String,
val subscriptions_url: String,
val twitter_username: Any,
val type: String,
val updated_at: String,
val url: String
) : Serializable
but every time I try to insert data into the table I am getting the error, how can I insert null data object in table while using room database?
The issue here is that Room doesn't know how to insert attribute of type Profile to the table.
The simple solution would be to use a type converter. Something like the following:
class DatabaseConverters {
#TypeConverter
fun toProfile(profileJson: String): Profile? {
return <Create a Profile object out of a JSON string>
}
#TypeConverter
fun fromProfile(profile: Profile?): String {
return <JSON string representation of Profile object>
}
}
In your case - you can use "" (empty string) when Profile is null.
More info about converters: Here
I have entity
#Entity
data class SegmentEntity(
#PrimaryKey(autoGenerate = true)
val id: Long,
var rideRelatedId: Long?,
var name: String?,
var speed: String?
)
And I wish that PrimaryKey will be autogenerated, but when I build this entry I require to add it to constructor:
SegmentEntity(0,3,"Dan","90")
How can I autogenerate ids without adding it constructor
you can change your data class to bellow and put your id out of contractor:
#Entity
data class SegmentEntity(
var rideRelatedId: Long?,
var name: String?,
var speed: String?
) {
#PrimaryKey(autoGenerate = true)
val id: Long? = null;
}
or can set default value null to your id look like this:
#Entity
data class SegmentEntity(
#PrimaryKey(autoGenerate = true)
val id: Long? = null,
var rideRelatedId: Long?,
var name: String?,
var speed: String?
)
in this case you must call your class :
SegmentEntity(name = "nameValue",rideRelatedId = 1 ,speed ="speedValue")
Your model should look like this :
#Entity
data class SegmentEntity(
#PrimaryKey(autoGenerate = true)
val id: Long = 0L,
var rideRelatedId: Long?,
var name: String?,
var speed: String?
And then you can do SegmentEntity(3,"Dan","90") with incremented id after insertion in your database
I think that this is currently best practice to do this:
#Entity
data class SegmentEntity(
var rideRelatedId: Long?,
var name: String?,
var speed: String?
) {
#PrimaryKey(autoGenerate = true)
var id: Int? = null
}
I'm in situation where i have other model classes nested inside a parent class , and the thing is that i want to insert the model classes into room db but it is asking me to use type converter but i don't know to and from which type should i convert the data class , this is my code
data class FixturesMergedModels (
#Embedded var event: Event,
#Embedded var teamXX: TeamXX,
#Embedded var awaylogo: testAwayLogoModel
)
My Event Model
#Entity
data class Event(
#PrimaryKey(autoGenerate = true)
var evenid : Int?,
#SerializedName("dateEvent")
var dateEvent : String?,
#SerializedName("strTime")
val strTime : String?,
#SerializedName("strThumb")
val strThumb : String?,
#SerializedName("strHomeTeam") //
val strHomeTeam : String?,
#SerializedName("strAwayTeam") //
val strAwayTeam : String?,
#SerializedName("idAwayTeam")
val idAwayTeam: Int?,
#SerializedName("idEvent")
val idEvent: Int?,
#SerializedName("idHomeTeam")
val idHomeTeam : Int?,
#SerializedName("intHomeScore") //
val intHomeScore : String?,
#SerializedName("intAwayScore") //
val intAwayScore : String?
)```
* Home Team Model ( teamxx)
#Entity
data class TeamXX(
#PrimaryKey(autoGenerate = true)
var homeTeamID : Int?,
#SerializedName("strTeamBadge")
val HomestrTeamBadge: String?
)```
Away Team Model
data class testAwayLogoModel (
#PrimaryKey(autoGenerate = true)
var awayTeamID : Int?,
#SerializedName("strTeamBadge")
val AwaystrTeamBadge: String?
)
According to the google developer website, you should use #Embedded for your event and teamXX class. Here is a short example given at their website.
data class Address(
val street: String?,
val state: String?,
val city: String?,
#ColumnInfo(name = "post_code") val postCode: Int)
#Entity
data class User(
#PrimaryKey val id: Int,
val firstName: String?,
#Embedded val address: Address?
)
for more detail you can visit here: https://developer.android.com/training/data-storage/room/relationships