如何在 RoomDatabase 中存储枚举的数组列表



我的问题是如何存储

List<Enum>

在房间数据库中, 到目前为止,我找不到答案。

枚举:

public enum HelloEnum {
A,
B,
C
}

转炉:

public class EnumConverter {
@TypeConverter
public List<HelloEnum> storedStringToEnum(String value) {
List<String> dbValues = Arrays.asList(value.split("\s*,\s*"));
List<HelloEnum> enums = new ArrayList<>();
for (String s: dbValues)
enums.add(HelloEnum.valueOf(s));
return enums;
}
@TypeConverter
public String languagesToStoredString(List<HelloEnum> cl) {
String value = "";
for (HelloEnum lang : cl)
value += lang.name() + ",";
return value;
}    
}

在插入和获取数据方面,这将工作,而不是提出的问题。

@Dao
public interface HelloPojoDao {
@Query("SELECT * FROM helloPojo")
List<HelloPojo> fetchAll();
@Insert
void insertPojo(HelloPojo pojo);
}

但是,我要指出的是,枚举过滤现在变得更加棘手。例如,如果要编写用于获取包含枚举的对象的查询。A 和枚举。B,您必须构建一个查询它们的字符串对象的查询。在本例中,"SELECT * FROM pojo WHERE enums 包含 'A'和 ' B'。因此,最好为枚举分配数字值(如@Kuffs答案详细信息),因为解析整数可能比解析字符串产生更少的问题。

希望这可以解决您的问题。随时在评论区提出任何问题,祝您狩猎愉快!

使用Kotlin 要简单得多,当使用name

class EnumTypeConverter {
@TypeConverter
fun restoreEnum(enumName: String): EnumType = EnumType.valueOf(enumName)
@TypeConverter
fun saveEnumToString(enumType: EnumType) = enumType.name
}

让我展示使用 kotlin 持久化/检索它的方法。

我们在手术过程中有什么限制?

  • 我们将枚举列表存储为数据库中的字符串字段,因此我们无法基于它在数据库中进行有效的选择或搜索
  • 我们必须将每个枚举值序列化为字符串并将其反序列化
  • 我们不能将行为基于序数字段以防止将来由于扩展枚举而导致的错误,因此我们需要有一个常量字段来表示每个枚举值
    • 我们不能基于默认toString列表到字符串的方法,因为它可能取决于我们完全使用的环境

所以在我看来,正确的实现将是这样的:

  1. 创建所有持久化到 db 的枚举类都应实现Enumerable接口
  2. 每个枚举类都应该有创建方法,并向其传递序列化参数,以恢复枚举值
  3. 创建 kotlin 扩展以序列化/反序列化枚举列表
  4. 为每种类型的枚举创建类型转换器

因此,可枚举接口:

/** marks the enum with custom int code for each value */
interface Enumerable {
val code: Int
}

枚举示例:

enum class PaymentSystemEntity constructor(
override val code: Int
) : Enumerable {
VISA(1),
MASTERCARD(2),
UNKNOWN(0);
companion object {
fun parseFromCode(code: Int): PaymentSystemEntity = values()
.firstOrNull { it.code == code } ?: UNKNOWN
}
}

序列化扩展:

fun <T> List<T>.asString(): String where T : Enum<T>, T : Enumerable = this
.map { it.code }
.joinToString(separator = ",")
fun <T> String.toEnumList(creator: (code: Int) -> T): List<T> where T : Enum<T>, T : Enumerable = this
.split(',')
.map { it.toInt() }
.map { creator(it) }

枚举的样本类型转换器:

class PaymentSystemTypeConverter {
@TypeConverter
fun paymentSystemsToString(value: List<@JvmSuppressWildcards PaymentSystemEntity>): String =
value.asString()
@TypeConverter
fun stringToPaymentSystems(value: String): List<@JvmSuppressWildcards PaymentSystemEntity> =
value.toEnumList { PaymentSystemEntity.parseFromCode(it) }
}

您可能以相同的方式实现其他类型的集合

将枚举序列化为整数并存储它们。

检索值时,请执行反向操作。

这两个操作在我对这个问题的回答中都有解释:

如何将 int 与枚举匹配

Kotlin 中的 Jack Dalton 版本:

@TypeConverter
fun storedStringListLineType(value: String): List<LineType> {
val dbValues = value.split("\s*,\s*".toRegex()).dropLastWhile { it.isEmpty() }
val enums: MutableList<LineType> = ArrayList()
for (s in dbValues)
enums.add(LineType.valueOf(s))
return enums
}
@TypeConverter
fun listLineTypeToStoredString(listLineTypes: List<LineType>): String {
var value = ""
for (lineType in listLineTypes)
value += lineType.name + ","
return value
}

最新更新