Sam Chen
Sam Chen

Reputation: 8857

Android Room Entity Enum Field Causes Build Failed

I noticed that since Room 2.3.0-alpha04 it supports Enum field for the Entity (from this post), so I try but failed...

My Gender Enum:

enum class Gender(val value: String) {
    MALE("Male"),
    FEMALE("Female"),
    UNKNOWN("Unknown")
}

My Entitiy:

@Entity(tableName = "student")
data class Student(
    var name: String,
    var age: Int,
    var gender: Gender    //<- Enum
) {
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

My Dao:

@Dao
interface StudentDao {
    @Query("SELECT * FROM student")
    fun getAllStudentsFlow(): Flow<List<Student>>

    @Insert
    suspend fun insert(student: Student)

    @Query("SELECT COUNT(name) FROM student WHERE name = :name")
    suspend fun getNameCount(name: String): Int
}

I'm using the latest version:

implementation "androidx.room:room-runtime:2.4.0-beta02"
implementation "androidx.room:room-ktx:2.4.0-beta02"
kapt "androidx.room:room-compiler:2.4.0-beta02"

And getting this error:

> Task :app:compileDebugJavaWithJavac FAILED
 C:\...\com\example\roomwithenum\database\StudentDao_Impl.java:87: ����: �޷����� 
Student�еĹ����� StudentӦ�õ���������;
            _item = new Student();
                ^
  ��Ҫ: String,int,Gender
  �ҵ�: û�в���
  ԭ��: ʵ�ʲ����б����ʽ�����б��Ȳ�ͬ
1 ������

Any help will be appreciated.

Upvotes: 0

Views: 812

Answers (2)

MikeT
MikeT

Reputation: 56948

so I try but failed...

Well using you code and dependencies as per :-

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    implementation 'androidx.room:room-ktx:2.4.0-beta02'
    implementation 'androidx.room:room-runtime:2.4.0-beta02'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    kapt 'androidx.room:room-compiler:2.4.0-beta02'
    kapt 'androidx.lifecycle:lifecycle-compiler:2.4.0'
}

Then it compiles fine and the section of StudentDao_Impl that is garbled in your case compiles as ):-

  @Override
  public List<Student> call() throws Exception {
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
      final int _cursorIndexOfAge = CursorUtil.getColumnIndexOrThrow(_cursor, "age");
      final int _cursorIndexOfGender = CursorUtil.getColumnIndexOrThrow(_cursor, "gender");
      final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
      final List<Student> _result = new ArrayList<Student>(_cursor.getCount());
      while(_cursor.moveToNext()) {
        final Student _item;
        final String _tmpName;
        if (_cursor.isNull(_cursorIndexOfName)) {
          _tmpName = null;
        } else {
          _tmpName = _cursor.getString(_cursorIndexOfName);
        }
        final int _tmpAge;
        _tmpAge = _cursor.getInt(_cursorIndexOfAge);
        final Gender _tmpGender;
        _tmpGender = __Gender_stringToEnum(_cursor.getString(_cursorIndexOfGender));
        _item = new Student(_tmpName,_tmpAge,_tmpGender);
        final long _tmpId;
        _tmpId = _cursor.getLong(_cursorIndexOfId);
        _item.setId(_tmpId);
        _result.add(_item);
      }
      return _result;
    } finally {
      _cursor.close();
    }
  }

  @Override
  protected void finalize() {
    _statement.release();
  }
});

About 2/3rds down is line _item = new Student(_tmpName,_tmpAge,_tmpGender);

Yours is garbled by this stage but is interestingly showing _item = new Student(); as if _tmpName _tmpAge and _tmpGender don't exist.

The garbled data is as if a byte stream has corrupted the generated code.

I'd suggest trying a clean and rebuild, perhaps exiting Android Studio and returning. There appears to be nothing wrong with your code

----

P.S. you commented in regard to TypeConverters saying I thought the new version will provide this automatically by default...

You are correct, in StudentDao_Impl it includes :-

  private String __Gender_enumToString(final Gender _value) {
    if (_value == null) {
      return null;
    } switch (_value) {
      case MALE: return "MALE";
      case FEMALE: return "FEMALE";
      case UNKNOWN: return "UNKNOWN";
      default: throw new IllegalArgumentException("Can't convert enum to string, unknown enum value: " + _value);
    }
  }

  private Gender __Gender_stringToEnum(final String _value) {
    if (_value == null) {
      return null;
    } switch (_value) {
      case "MALE": return Gender.MALE;
      case "FEMALE": return Gender.FEMALE;
      case "UNKNOWN": return Gender.UNKNOWN;
      default: throw new IllegalArgumentException("Can't convert value to enum, unknown value: " + _value);
    }
  }

P.S. I've also include your code in another answer that'd given compiled and run with beta02 and shows (after clicking Insert a few times) :-

enter image description here

So certainly no problems with your code.

Upvotes: 1

rost
rost

Reputation: 4075

Store enums in DB in primitive types like a string. Best pratice for you is using @TypeConverters

class TypeConverters {

     @TypeConverter
     fun toGender(value: String) = enumValueOf<Gender>(value)

     @TypeConverter
     fun fromGender(value: Gender) = value.name
}

And annotate your database class with

@TypeConverters(Converters::class)

refer https://developer.android.com/reference/android/arch/persistence/room/TypeConverter

Upvotes: 0

Related Questions