可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm integrating with the Room persistence library. I have a data class in Kotlin like:
@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
)
The @Entity
and @PrimaryKey
annotations are for the Room library. When I try to build, it is failing with error:
Error:Cannot find setter for field.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
I also tried providing a default constructor:
@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, "", "", "")
}
But this doesn't work as well. A thing to note is that it works if I convert this Kotlin class into a Java class with getters and setters. Any help is appreciated!
回答1:
Since your fields are marked with val
, they are effectively final and don't have setter fields.
Try switching out the val
with var
.
You might also need to initialize the fields.
@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 = ""
)
回答2:
Hey I don't know if everyone know or not, but you can not have column which is starting from is
into Room
.
For example you can't have like this
@Entity(tableName = "user")
data class User (
@PrimaryKey var id: Long? = null,
var userName: String = "",
var isConnectedToFB: Boolean = false,
)
回答3:
This is a bug and is fixed in Room 2.1.0-alpha01
https://developer.android.com/jetpack/docs/release-notes#october_8_2018
Bug Fixes
- Room will now properly use Kotlin’s primary constructor in
data classes avoiding the need to declare the fields as vars.
b/105769985
回答4:
There is an issue in room db library java code generation.
I was using optional field isFavorite
. It gives me same error then I change my field name to favorite
then compiled.
before
var isFavorite: Int? = 0,
after changing working fine
var favorite: Int? = 0,
Thanks
回答5:
According to https://stackoverflow.com/a/46753804/2914140 if you have an autogenerated primary key, you should write so:
@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
}
Note that @PrimaryKey
is written inside the class body and contains modifier var
.
If you later want to update a row in a database with different parameters, use these lines:
val newStory = story.copy(by = "new author", title = "new title") // Cannot use "id" in object cloning
newStory.id = story.id
dao.update(newStory)
UPDATE
I still don't use AndroidX, and Room is 'android.arch.persistence.room:runtime:1.1.1'.
You can extend this class from Serializable
. But if you want to extend it from Parcelable
, you will get a warning (over id
variable): Property would not be serialized inro a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove this warning
:
Then I moved an id
from the body to the constructor. In Kotlin I use @Parcelize
to create Parcelable
classes:
@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
回答6:
Had this error in Java.
You cannot have a column starting with is
or is_
in Java.
Try renaming the column.
Another solution:
You either have to pass the field in the constructor and initialize it with the constructor argument, or create a setter for it.
Example:
public MyEntity(String name, ...) {
this.name = name;
...
}
public void setName(String name) {
this.name = name;
}
回答7:
Another cause of this may be the naming of the field. If you use any of the pre-defined keywords, you will get the same error.
For instance, you can not name your column "is_active".
Reference: http://www.sqlite.org/lang_keywords.html
回答8:
Just an update if somebody comes across this thread in 2019, after spending hours digging online on why this should work, but it doesn't.
Using val
works as expected if you are using the AndroidX version ( androidx.room:room-<any>:2.*
) but it doesn't when using the old android.arch.persistence.room:<any>:1.1.1
and it seems that version 2.*
wasn't released on this latter repo.
Edit: typos
回答9:
If you want the val
immutability available for your entity, it is possible.
- You should update to AndroidX room current version.
- Check for the related issue here it is marked as Won't Fix
- Now they have release a fix related to the issue with version 2.0.0-beta01
- Now you can use immutable
val
with default value
e.g:
@Entity("tbl_abc")
data class Abc(
@PrimaryKey
val id: Int = 0,
val isFavourite: Boolean = false
)
Previously, the above snippet will throw an error of Cannot find setter for field
. Changing into var
is a great workaround, but I prefer for the entity class to be immutable from outside invocation
回答10:
You can now start your field with is
but you can't have a number next to the is
like : is2FooSelected
, you have to rename to isTwoFooSelected
.