📑

Room ORMで予約語を使ったら面倒なことになった件

2022/05/21に公開

はじめに

AndroidのRoom ORMを使ってネットワークから取得したデータを永続化する処理を書いていたところ、
永続化処理自体には成功しているものの全てのデータの特定のフィールドに初期値が入ってしまうという不具合が発生してしまっていました。

何故問題が発生したのか

以下のようなEntityを作成していたわけですが、
感のいい方なら既にお分かりかもしれませんが、フィールドにcharという文字を使っていることが、原因になりました。

@Entity(tableName = "utf8_emojis", primaryKeys = ["codes"])
data class Utf8EmojiDTO(
    @ColumnInfo(name = "codes") var codes: String,
    @ColumnInfo(name = "name") var name: String,
    @ColumnInfo(name = "char") var char: String,
) {
    constructor() : this("", "", "")
}

発生した理由

ColumnInfo(name = "char")の方は問題はなかったのですが、
どうやらフィールドのcharの方に問題があったらしく、
基本的にRoom ORMはJavaのコードを生成していい感じにしてくれているわけですが、
charというJavaの予約語を使用したことによって、
うまく動作してくれず、SQLite上にもcharカラムが生成されないままになってしまいました。
実はエラー自体は発生していて、デフォルトコンストラクタとsetterを作ってくれ的なエラーが出ていました。
本来はここで予約語問題に気がつくべきでしたが、そのまま愚直に従ってしまったため、問題を見過ごすことになりました。

解決策

Kotlinのフィールド名を変更しました。
この場合新たにColumnが作成された扱いになるので、
既にリリースしてしまっている場合はMigrationをする必要があります。

@Entity(tableName = "utf8_emojis_by_amio", primaryKeys = ["codes"])
data class Utf8EmojiDTO(
    @ColumnInfo(name = "codes") var codes: String,
    @ColumnInfo(name = "name") var name: String,
    @ColumnInfo(name = "char") var charCode: String,
)

まとめ

  • Room ORMのEntityでJavaの予約後を使ってはいけない

参考

https://qiita.com/RyuNen344/items/ac348100df690aedb066

Discussion