Debo escribir el valor de la enum
enumeración a la base de datos. Se produce un error durante la compilación. ¿Qué estoy haciendo mal?
No se puede averiguar cómo guardar este campo en la base de datos. Puede considerar agregar un convertidor de tipos para ello.
@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
}
}
}
allan veloso
Puede hacer una conversión a cada enumeración, así:
class Converters {
@TypeConverter
fun toHealth(value: String) = enumValueOf<Health>(value)
@TypeConverter
fun fromHealth(value: Health) = value.name
}
O si prefiere almacenarlo como SQL integer
también puedes usar ordinal:
class Converters {
@TypeConverter
fun toHealth(value: Int) = enumValues<Health>()[value]
@TypeConverter
fun fromHealth(value: Health) = value.ordinal
}
Desafortunadamente, no hay forma de usar genéricos Enum<T>
para lograr esto, ya que los genéricos no vinculados generarán un error Cannot use unbound generics in Type Converters
.
El equipo de Android Room podría agregar seriamente una anotación y un generador para Enums a su compilador kapt.
Finalmente, anote una clase de base de datos, clase de entidad, clase dao, método dao, parámetro de método dao o clase de campo de entidad con esto:
@TypeConverters(Converters::class)
-
¿Cómo usar la enumeración en la clase de datos? Con el valor o enumeración?
– Rafael
12 de noviembre de 2020 a las 15:50
-
@Rafael Después de usar el convertidor de tipos, puede usar directamente la enumeración en su clase de entidad.
– Sarthak_ssg5
30 de octubre de 2021 a las 5:03
Esto ya no es un problema en versión 2.3.0-alpha4: “Room ahora usará de forma predeterminada un convertidor de tipo Enum a String y viceversa si no se proporciona ninguno. Si ya existe un convertidor de tipo para una enumeración, Room priorizará su uso sobre el predeterminado”.
“Si ya existe un convertidor de tipo unidireccional para lectura para el Enum, Room podría usar accidentalmente el convertidor de cadena a Enum incorporado que podría no ser deseado. Este es un problema conocido y se puede solucionar convirtiéndolo en un convertidor bidireccional convertidor.”
Semidiós
Para arreglar esto, anote su Database
clase con @TypeConverters
anotación (y no su enum class
).
Ejemplo:
@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
Controlar https://developer.android.com/training/data-storage/room/referencing-data
-
¿Hay alguna otra manera? En JPA es mucho más fácil.
– Alan Veloso
1 de febrero de 2020 a las 16:50
-
@AllanVeloso, ¿qué quieres tener como “otro camino”? Alternativamente, puede contener datos de tipo básico en sus modelos (como enum ordinal como
Int
o enum nombre comoString
, etc.), pero ¿será mejor? Además, no sé qué es el JPA …– Semidiós
3 de febrero de 2020 a las 11:31
-
JPA = API de persistencia de Java. Maneja la persistencia de las clases Enum con una simple anotación @Enumerated(EnumType.STRING) o @Enumerated(EnumType.ORDINAL) en el campo. De esta manera, no necesita crear un convertidor para cada enumeración.
– Alan Veloso
3 de febrero de 2020 a las 23:06
-
@AllanVeloso, tal vez seguir una sola interfaz por todas las enumeraciones es lo que podría ayudar. He agregado a mi respuesta.
– Semidiós
4 de febrero de 2020 a las 10:43
-
Tampoco es bueno, cada vez que defina una opción de enumeración, tendrá que anular el método getId(). Traté de usar genéricos, rectificados en línea y genéricos. pero room tampoco lo soporta, error
Cannot use unbound generics in Type Converters
. Mejor convertirlo manualmente.– Alan Veloso
5 de febrero de 2020 a las 15:16
clase de enumeración;
enum class Priority {
HIGH,
MEDIUM,
LOW
}
Clase de convertidor;
class Converter {
@TypeConverter
fun fromPriority(priority: Priority): String {
return priority.name
}
@TypeConverter
fun toPriority(priority: String): Priority {
return Priority.valueOf(priority)
}
}
uso;
@Database(entities = [MyData::class], version = 1, exportSchema = false)
@TypeConverters(Converter::class)
abstract class MyDatabase : RoomDatabase() {
// todo
}
Zain
Para desarrolladores java
La enumeración
public enum Health {
NONE(-1),
VERY_BAD(0);
public final int value;
Health(int newValue) {
value = newValue;
}
public int getValue() {
return value;
}
}
El convertidor de tipos
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]);
}
}
Waran-
Desde la versión 2.3.0 de Room puedes guardar Enum Look aquí https://developer.android.com/jetpack/androidx/releases/room?hl=ru#version_230_3
Parece que deberías anotar tu
Database
clase con@TypeConverters
anotación (y no suenum class
). Controlar desarrollador.android.com/entrenamiento/almacenamiento de datos/habitación/…– Semidiós
2 ago. 2019 a las 12:50
@Demigod sí, esto funciona. Puedes escribir respuesta
– Visto
2 de agosto de 2019 a las 13:07