Viewed
Viewed

Reputation: 1413

How to save enum field in the database room?

I must write the value from the enum enumeration to the database. An error occurs during compilation. What am I doing wrong?

Cannot figure out how to save this field into database. You can consider adding a type converter for it.

@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
        }
    }

}

Upvotes: 59

Views: 40571

Answers (6)

Allan Veloso
Allan Veloso

Reputation: 6369

Update:

Since version 2.3.0, Room allows automatic conversion of enums using the name (as a TEXT in the SQLite database).

Old answer:

You can make a convert to each enum, like this:

class Converters {

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

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

Or if you prefer store it as SQL integer, you can use ordinal too:

class Converters {

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

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

Unfortunatally, there is no way to use generics Enum<T> to accomplish this since unbound generics will raise an error Cannot use unbound generics in Type Converters.

Android Room team could seriously add an annotation and a generator for Enums to their kapt compiler.

Finally, annotate a database class, entity class, dao class, dao method, dao method parameter or entity field class with this:

@TypeConverters(Converters::class)

Upvotes: 74

Mikhail Valuyskiy
Mikhail Valuyskiy

Reputation: 1288

Since Room version 2.3.0 you can save Enum Look here: https://developer.android.com/jetpack/androidx/releases/room?#version_230_3

Upvotes: 3

Chr
Chr

Reputation: 401

This is no longer an issue in version 2.3.0-alpha4: "Room will now default to using an Enum to String and vice versa type converter if none is provided. If a type converter for an enum already exists, Room will prioritize using it over the default one."

"If a one-way type converter for reading already exists for the Enum, Room might accidentally use the built-in String to Enum converter which might not be desired. This is a known issue and can be fixed by making it a two-way converter."

Upvotes: 40

Ahmet B.
Ahmet B.

Reputation: 1674

Enum class;

enum class Priority {
HIGH,
MEDIUM,
LOW
}

Converter class;

class Converter {

@TypeConverter
fun fromPriority(priority: Priority): String {
    return priority.name
}

@TypeConverter
fun toPriority(priority: String): Priority {
    return Priority.valueOf(priority)
}

}

usage;

@Database(entities = [MyData::class], version = 1, exportSchema = false)
@TypeConverters(Converter::class)
abstract class MyDatabase : RoomDatabase() {

  // todo

}

Upvotes: 11

Zain
Zain

Reputation: 40840

For java developers

The Enum

public enum Health {
    NONE(-1),
    VERY_BAD(0);

    public final int value;

    Health(int newValue) {
        value = newValue;
    }

    public int getValue() {
        return value;
    }
}

The type converter

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

}

Upvotes: 5

Demigod
Demigod

Reputation: 5635

To fix this annotate your Database class with @TypeConverters annotation (and not your enum class).

Example:

@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Check https://developer.android.com/training/data-storage/room/referencing-data

Upvotes: 15

Related Questions