7

我的问题是如何存储

List<Enum>

在 RoomDatabase 中,到目前为止我没有找到答案。

4

5 回答 5

8

枚举:

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);
}

但是,我要指出,现在按枚举进行过滤变得更加棘手。例如,如果您想编写一个查询来获取包含 enum.A 和 enum.B 的对象,则必须构建一个查询来为它们查询字符串对象。在这种情况下,“SELECT * FROM pojo WHERE enums contains 'A,' and 'B,'。因此,最好为您的枚举分配数字值(作为@Kuffs 答案详细信息),因为解析整数可能会产生比解析字符串。

希望这能解决您的问题。欢迎在评论区提出任何问题,祝您狩猎愉快!

于 2017-06-22T12:57:57.987 回答
4

好的,使用 Kotlin 更简单,当使用name

class EnumTypeConverter {

    @TypeConverter
    fun restoreEnum(enumName: String): EnumType = EnumType.valueOf(enumName)

    @TypeConverter
    fun saveEnumToString(enumType: EnumType) = enumType.name
}
于 2018-01-22T09:31:24.910 回答
1

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

在操作过程中我们有什么限制?

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

因此,在我看来,正确的实施将如下所示:

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

因此,Enumerable 接口:

/** 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) }

}

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

于 2019-05-29T10:26:19.590 回答
0

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

检索值时,执行相反的操作。

我对这个问题的回答中解释了这两种操作:

如何将int与枚举匹配

于 2017-06-22T11:53:30.940 回答
0

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
}
于 2019-09-20T11:06:30.440 回答