【问题标题】:How to save enum field in the database room?如何在数据库室中保存枚举字段?
【发布时间】:2019-12-11 02:23:52
【问题描述】:

我必须将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


【解决方案1】:

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

class Converters {

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

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

或者,如果您更喜欢将其存储为 SQL integer,您也可以使用 ordinal:

class Converters {

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

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

不幸的是,没有办法使用泛型 Enum&lt;T&gt; 来完成此操作,因为未绑定的泛型会引发错误 Cannot use unbound generics in Type Converters

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

最后,对一个数据库类、实体类、dao类、dao方法、dao方法参数或实体字段类进行注解:

@TypeConverters(Converters::class)

【讨论】:

  • 如何在数据类中使用枚举?用值还是枚举?
  • @Rafael 使用类型转换器后,你可以直接在你的实体类中使用枚举。
【解决方案2】:

要解决此问题,请使用 @TypeConverters 注释(而不是 enum class)注释您的 Database 类。

例子:

@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

【讨论】:

  • 还有其他方法吗?在 JPA 中要容易得多。
  • @AllanVeloso,你想要什么作为“其他方式”?或者,您可以在模型中保存基本类型数据(例如枚举序号为Int,或枚举名称为String 等),但它会更好吗?还有,不知道JPA是什么...
  • JPA = Java 持久性 API。它使用字段上的简单注释 @Enumerated(EnumType.STRING) 或 @Enumerated(EnumType.ORDINAL) 处理 Enum 类的持久性。这样你就不需要为每个枚举创建一个转换器。
  • @AllanVeloso,也许所有枚举都遵循一个接口可能会有所帮助。我已添加到我的答案中。
  • 也不好,每次定义枚举选项时,都必须重写 getId() 方法。我尝试使用泛型、内联修饰和泛型。但是房间也不支持它,错误Cannot use unbound generics in Type Converters。最好手动转换。
【解决方案3】:

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

“如果 Enum 已经存在用于读取的单向类型转换器,Room 可能会意外使用内置的 String 到 Enum 转换器,这可能是不需要的。这是一个已知问题,可以通过将其设置为双向转换器。”

【讨论】:

    【解决方案4】:

    枚举类;

    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
    
    }
    

    【讨论】:

    • “转换器”类是否可以包含您想要的所有转换器?
    • @androiddeveloper 是的
    • @Milan Nice。谢谢你。
    【解决方案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]);
        }
    
    }
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-09
        • 1970-01-01
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2019-10-02
        • 2014-08-07
        相关资源
        最近更新 更多