Here's my Entity:
@Entity(tableName = "commits")
data class Commit(
@PrimaryKey
@ColumnInfo(name = "hash")
val hash: String,
@ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB)
var changes: List<DbChange>
)
And here's the converters:
class Converters {
companion object {
@JvmStatic
@TypeConverter
fun changesToByteArray(changes: List<DbChange>): ByteArray {
...
}
@JvmStatic
@TypeConverter
fun byteArrayToChanges(bytes: ByteArray): List<DbChange> {
...
}
}
}
And I've already added Converters class to the annotations:
@Database(entities = [Commit::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppRoomDatabase : RoomDatabase() {
...
}
But the compiler still complains:
e: /home/perqin/workspaces/cent-budget/cent-budget/app/build/tmp/kapt3/stubs/eaDebug/com/perqin/centbudget/data/sync/commit/Commit.java:20: error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private java.util.List<? extends com.perqin.centbudget.data.sync.changes.DbChange> changes;
How to solve this issue? I have no ideas at all...
This is actually Kotlin's fault rather than Room's.
As you can see in your error message you get List<? extends DbChange>
instead of List<DbChange>
for changes
field and thus Room tried to find TypeConverters
for byte[] -> List<? extends DbChange>
and List<? extends DbChange> -> byte[]
, but fails to do so.
That's because changesToByteArray
method argument type is generated as List<? extends DbChange>
, but type of byteArrayToChanges
method is still List<DbChange>
and thus you get a compilation error.
I would recommend this article if you want read more.
Solution 1:
Use @JvmSuppressWildcards
Annotate Commit
class so that type without wildcards will be generated for changes
field and it's setter:
@Entity(tableName = "commits")
@JvmSuppressWildcards
data class Commit(
@PrimaryKey
@ColumnInfo(name = "hash")
val hash: String,
@ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB)
var changes: List<DbChange>
)
Annotate List
's type for same reason:
class Converters {
companion object {
@JvmStatic
@TypeConverter
fun changesToByteArray(changes: List<@JvmSuppressWildcards DbChange>): ByteArray {
...
}
@JvmStatic
@TypeConverter
fun byteArrayToChanges(bytes: ByteArray): List<DbChange> {
...
}
}
}
Solution 2:
Create wrapper class for your list like:
data class DbChanges(val list: List<DbChange>)
and then update Commit
class:
@Entity(tableName = "commits")
data class Commit(
@PrimaryKey
@ColumnInfo(name = "hash")
val hash: String,
@ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB)
var changes: DbChanges
)
and write new TypeConverters
:
class Converters {
companion object {
@JvmStatic
@TypeConverter
fun changesToByteArray(changes: DbChanges): ByteArray {
...
}
@JvmStatic
@TypeConverter
fun byteArrayToChanges(bytes: ByteArray): DbChanges {
...
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With