对房间实体使用 kotlin.UByte 无效

Using kotlin.UByte for Room Entity not working

我想在我的房间数据库中存储以下数据class。不知何故,我没有成功:

@Entity
data class UInt8(
    @PrimaryKey(autoGenerate = true)
    var key: Int,
    var name: String = "uint8-test",
    var value: UByte = 0.toUByte(),
    var size: Int = 1,
    var readOnly: Boolean = true
) 

我的自动生成的构建文件总是出错:

C:<...>\UInt8.java:15: error: Cannot find getter for field.
    private byte value;
Cannot find getter for field.

UShortUIntULong 相同。

但是,如果我用 Int 替换它,它似乎可以工作,但不是我想要的(它需要是一个 UByte。


build.grade(来自developer.android.com):

def room_version = "2.4.2"

//implementation "androidx.room:room-runtime:$room_version"
//annotationProcessor "androidx.room:room-compiler:$room_version"


implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:2.5.0-alpha01"
// kapt "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.2.0"
// optional - RxJava2 support for Room

implementation "androidx.room:room-rxjava2:$room_version"

// optional - RxJava3 support for Room
implementation "androidx.room:room-rxjava3:$room_version"

// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"

// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"

// optional - Paging 3 Integration
implementation "androidx.room:room-paging:2.5.0-alpha01"

更新 1:
我的 TypeConverter (Converters.kt) 如下所示:

class Converters {
    @TypeConverter
    fun uByteToInt(uByte: UByte): Int = uByte.toInt()
    @TypeConverter
    fun intToUByte(value: Int): UByte = value.toUByte()
}

AppDatabase.kt:

@Database(entities = [<...>::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun sensorDao(): SensorDao
    ...
}

更新二:
可能值得注意的是 Class UInt8 是另一个实体中的嵌套 class,即:

@Entity()
data class  simpleConfig(
    @Embedded(prefix = "simplec_version_") val version: UInt8 = 
    UInt8("Field Version"),
...)
   

我认为这很可能是一个错误。

如果你有 UInt8,那么 Room 会生成 AppDatabase_Impl,table 将 UByte 识别为整数,例如

_db.execSQL("CREATE TABLE IF NOT EXISTS `UInt8` (`key` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `testvalue` INTEGER NOT NULL, `size` INTEGER NOT NULL, `readOnly` INTEGER NOT NULL)");
  • 按照createAllTables方法
  • 注意值已更改为测试值以确保重新生成它。

因此 Room 理解 UByte 等同于 INTEGER 列类型。

我认为,问题在于它正在处理 expects Int,因此默认的 getter 和 setter 不足。此外,TypeConverters 被忽略了,因为 Room 显然知道如何处理。

如果您改为使用:-

@Entity
data class UInt8(
    @PrimaryKey(autoGenerate = true)
    var key: Int,
    var name: String = "uint8-test",
    var testvalue: Int = 0,
    var size: Int = 1,
    var readOnly: Boolean = true
) {
    constructor(key: Int, name: String, testvalue: UByte, size: Int, readOnly: Boolean): this(key,name, testvalue.toInt(),size,readOnly)
}

然后 Room 没有抱怨,但是 testvalue 在检索它时会是一个 Int。但是,您需要将 getter 覆盖为 return 从 Int 到 Ubyte。

但是,如果您创建了一个 class 来掩盖 Room 如何处理 UByte,并实施 suitable 类型的转换器,那么它们就会发挥作用。

所以如果你有例如。

data class MyUByte(
    val value: UByte
)

并且有:-

@TypeConverter
fun myUByteToInt(myUByte: MyUByte): Int = myUByte.value.toInt()
@TypeConverter
fun intToMyUByte(value: Int): MyUByte = MyUByte(value.toUByte())

然后最后:-

@Entity
data class UInt8(
    @PrimaryKey(autoGenerate = true)
    var key: Int,
    var name: String = "uint8-test",
    var testvalue: MyUByte = MyUByte(0.toUByte()),
    var size: Int = 1,
    var readOnly: Boolean = true
)

那么 TypeConverters 就不会被忽略,编译就可以了。