如何在数据库室中保存枚举字段?
Posted
技术标签:
【中文标题】如何在数据库室中保存枚举字段?【英文标题】: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
【问题讨论】:
看起来你应该用@TypeConverters
注释(而不是你的enum class
)来注释你的Database
类。检查developer.android.com/training/data-storage/room/…
@Demigod 是的,这是可行的。你可以写答案
【参考方案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<T>
来完成此操作,因为未绑定的泛型会引发错误 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
【讨论】:
以上是关于如何在数据库室中保存枚举字段?的主要内容,如果未能解决你的问题,请参考以下文章