web-dev-qa-db-ja.com

フィールドのセッターが見つかりません-ルームデータベースでKotlinを使用

ルーム永続ライブラリと統合しています。 Kotlinには次のようなデータクラスがあります。

@Entity(tableName = "story")
data class Story (
        @PrimaryKey val id: Long,
        val by: String,
        val descendants: Int,
        val score: Int,
        val time: Long,
        val title: String,
        val type: String,
        val url: String
)

@Entityおよび@PrimaryKey注釈は、部屋ライブラリ用です。ビルドしようとすると、エラーで失敗します:

Error:Cannot find setter for field.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

また、デフォルトのコンストラクタを提供しようとしました:

@Entity(tableName = "story")
data class Story (
        @PrimaryKey val id: Long,
        val by: String,
        val descendants: Int,
        val score: Int,
        val time: Long,
        val title: String,
        val type: String,
        val url: String
) {
    constructor() : this(0, "", 0, 0, 0, "", "", "")
}

しかし、これもうまくいきません。注意すべきことは、このKotlinクラスをゲッターとセッターを含むJavaクラスに変換すれば機能するということです。どんな助けも大歓迎です!

49
gsb

フィールドにはvalのマークが付けられているため、事実上最終フィールドであり、セッターフィールドはありません。

valvarに切り替えてみてください。また、フィールドを初期化する必要があります。

@Entity(tableName = "story")
data class Story (
        @PrimaryKey var id: Long? = null,
        var by: String = "",
        var descendants: Int = 0,
        var score: Int = 0,
        var time: Long = 0L,
        var title: String = "",
        var type: String = "",
        var url: String = ""
)
126

誰もが知っているかどうかはわかりませんが、isからRoomに始まる列を持つことはできません。たとえば、あなたはこのようなことはできません

   @Entity(tableName = "user")
   data class User (
        @PrimaryKey var id: Long? = null,
        var userName: String = "",
        var isConnectedToFB: Boolean = false,
)
21
AJay

ルームdbライブラリJavaコード生成に問題があります。

オプションフィールドisFavoriteを使用していました。同じエラーが表示され、フィールド名をfavoriteに変更してからコンパイルします。

var isFavorite: Int? = 0,の前に正常に動作するvar favorite: Int? = 0,を変更した後、ありがとう

4
Qamar

https://stackoverflow.com/a/46753804/291414 に従って、自動生成された主キーがある場合は、次のように記述する必要があります。

@Entity(tableName = "story")
data class Story (
        val by: String,
        val descendants: Int,
        val score: Int,
        val time: Long,
        val title: String,
        val type: String,
        val url: String
)  {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
}

@PrimaryKeyはクラス本体内に記述され、修​​飾子varを含むことに注意してください。

後で異なるパラメーターを使用してデータベースの行を更新する場合は、次の行を使用します。

val newStory = story.copy(by = "new author", title = "new title") // Cannot use "id" in object cloning
newStory.id = story.id
dao.update(newStory)

更新

私はまだAndroidXを使用せず、Roomは「Android.Arch.persistence.room:runtime:1.1.1」です。

このクラスはSerializableから拡張できます。ただし、Parcelableから拡張する場合は、(id変数に対して)警告が表示されます:Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning

enter image description here

次に、idを本体からコンストラクターに移動しました。 Kotlinでは、@Parcelizeを使用してParcelableクラスを作成します。

@Parcelize
@Entity(tableName = "story")
data class Story (
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,

    val by: String,
    val descendants: Int,
    val score: Int,
    val time: Long,
    val title: String,
    val type: String,
    val url: String
) : Parcelable
3
CoolMind

これはバグであり、部屋2.1.0-alpha01で修正されています

https://developer.Android.com/jetpack/docs/release-notes#october_8_2018

バグの修正

  • ルームは、データクラスでKotlinのプライマリコンストラクターを適切に使用するようになり、フィールドを変数として宣言する必要がなくなりました。 b/105769985
3
triad

Javaでこのエラーが発生しました。

Javaでは、isまたはis_で始まる列を使用できません。

列の名前を変更してみてください。

別の解決策:

フィールドをコンストラクターに渡してコンストラクター引数で初期化するか、そのセッターを作成する必要があります。

例:

public MyEntity(String name, ...) {
   this.name = name;
   ...
}

public void setName(String name) {
    this.name = name;
}
2
live-love

エンティティでval不変性を使用できるようにする場合は、可能です。

  1. AndroidXルームに更新する必要があります 現在のバージョン
  2. 関連するものを確認してください 問題はこちら マークされている修正されない
  3. 現在、彼らは version 2.0.0-beta01 の問題に関連する修正をリリースしています
  4. これで、不変のvaldefault valueとともに使用できます。例:
@Entity("tbl_abc")
data class Abc(
    @PrimaryKey
    val id: Int = 0, 
    val isFavourite: Boolean = false
)

以前は、上記のスニペットはCannot find setter for fieldのエラーをスローします。 varへの変更は優れた回避策ですが、エンティティクラスは外部呼び出しから不変であることを好みます

1
mochadwi

これの別の原因は、フィールドの名前付けかもしれません。事前定義されたキーワードのいずれかを使用すると、同じエラーが発生します。たとえば、列に「is_active」という名前を付けることはできません。

リファレンス: http://www.sqlite.org/lang_keywords.html

1
dgngulcan

2019年に誰かがこのスレッドに出くわした場合、これがなぜ機能するのかオンラインで数時間かけて掘り下げた後の更新ですが、そうではありません。

valを使用すると、AndroidXバージョン(androidx.room:room-<any>:2.*)を使用している場合は期待どおりに機能しますが、古いAndroid.Arch.persistence.room:<any>:1.1.1を使用する場合は機能せず、バージョン2.*はこの後者のリポジトリでリリースされました。

編集:タイプミス

1
Jibbo