如何在数据库机房保存枚举字段?

问题描述 投票:0回答:6

我必须将

enum
枚举中的值写入数据库。编译时出现错误。我做错了什么?

无法弄清楚如何将此字段保存到数据库中。您可以考虑为其添加类型转换器。

@ColumnInfo(name = "state_of_health")
@TypeConverters(HealthConverter::class)
var health: Health

enum class Health(val value: Int){
    NONE(-1),
    VERY_BAD(0),
    ...
}

class HealthConverter{

    @TypeConverter
    fun fromHealth(value: Health): Int{
        return value.ordinal
    }

    @TypeConverter
    fun toHealth(value: Int): Health{
        return when(value){
            -1 -> Health.NONE
            0 -> Health.VERY_BAD
            ...
            else -> Health.EXCELLENT
        }
    }

}
android kotlin enums android-room converters
6个回答
73
投票

您可以对每个枚举进行转换,如下所示:

class Converters {

     @TypeConverter
     fun toHealth(value: String) = enumValueOf<Health>(value)

     @TypeConverter
     fun fromHealth(value: Health) = value.name
}

或者如果您更喜欢将其存储为 SQL

integer
,您也可以使用序数:

class Converters {

    @TypeConverter
    fun toHealth(value: Int) = enumValues<Health>()[value]

    @TypeConverter
    fun fromHealth(value: Health) = value.ordinal
}

不幸的是,没有办法使用泛型

Enum<T>
来完成此任务,因为未绑定的泛型会引发错误
Cannot use unbound generics in Type Converters

Android Room 团队可以认真地向他们的 kapt 编译器添加注释和枚举生成器。

最后,用这个注释一个数据库类、实体类、dao类、dao方法、dao方法参数或实体字段类:

@TypeConverters(Converters::class)

38
投票

这在 version 2.3.0-alpha4 中不再是问题:“Room 现在将默认使用枚举到字符串的类型转换器,如果没有提供,反之亦然。如果枚举的类型转换器已经存在,Room 将默认使用枚举到字符串的类型转换器。优先使用它而不是默认的。”

“如果枚举已经存在用于读取的单向类型转换器,Room 可能会意外地使用内置的字符串到枚举转换器,这可能是不需要的。这是一个已知问题,可以通过将其设为两层来解决方式转换器。”


15
投票

要解决此问题,请使用

Database
注释(而不是您的
@TypeConverters
)注释您的
enum class
类。

示例:

@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

检查https://developer.android.com/training/data-storage/room/referencing-data


11
投票

枚举类;

enum class Priority {
HIGH,
MEDIUM,
LOW
}

转换器类;

class Converter {

@TypeConverter
fun fromPriority(priority: Priority): String {
    return priority.name
}

@TypeConverter
fun toPriority(priority: String): Priority {
    return Priority.valueOf(priority)
}

}

使用;

@Database(entities = [MyData::class], version = 1, exportSchema = false)
@TypeConverters(Converter::class)
abstract class MyDatabase : RoomDatabase() {

  // todo

}

5
投票

对于 Java 开发者

枚举

public enum Health {
    NONE(-1),
    VERY_BAD(0);

    public final int value;

    Health(int newValue) {
        value = newValue;
    }

    public int getValue() {
        return value;
    }
}

类型转换器

public class HealthConverter {

    /**
     * Convert Health to an integer
     */
    @TypeConverter
    public static int fromHealthToInt(Health value) {
        return value.ordinal();
    }

    /**
     * Convert an integer to Health
     */
    @TypeConverter
    public static Health fromIntToHealth(int value) {
        return (Health.values()[value]);
    }

}

3
投票

从 Room 版本 2.3.0 开始,您可以保存 Enum 看这里: https://developer.android.com/jetpack/androidx/releases/room?#version_230_3

© www.soinside.com 2019 - 2024. All rights reserved.