我的 Room 数据库有问题。它由 2 个表“cast”、“movie”和一对一关系“movie_cast”组成。当我尝试构建项目时,出现以下错误:
error: Entities cannot have relations.
public final class MovieWithCastDbModel {
error: An entity must have at least 1 field annotated with @PrimaryKey
public final class MovieWithCastDbModel {
当我从 MovieWithCastDbModel 类中删除 @Entity 注释时,我得到以下内容
error: Entity class must be annotated with @Entity
public final class MovieWithCastDbModel {
所以无论我做什么,它都会告诉我做相反的事情。
以下是数据类本身:
@Entity(tableName = "cast")
data class CastDbModel(
@PrimaryKey(autoGenerate = false)
var id : Int,
var name: String,
var profile_path: String,
var character: String)
@Entity(tableName = "movie")
@TypeConverters(IntConverter::class)
data class MovieDbModel(
var page: Int,
@PrimaryKey(autoGenerate = false)
var id: Int,
var poster_path: String,
var overview: String,
var title: String,
@ColumnInfo(name = "genre_ids")
var genre_ids: Genres,
var runtime: Int)
@Entity(tableName = "movie_cast")
class MovieWithCastDbModel(
@Embedded
var movie: MovieDbModel,
@Relation(
entity = CastDbModel::class,
parentColumn = "id",
entityColumn = "id"
)
var cast : CastDbModel
)
data class Genres(
@Embedded
var genre_ids: Int
)
class IntConverter {
@TypeConverter
fun fromGenres(value: Genres): String {
return Gson().toJson(value)
}
@TypeConverter
fun toGenres(value: String): Genres {
return Gson().fromJson(value,Genres::class.java)
}
}
可能出现什么问题?
最佳答案
正如错误消息所示。实体不能有@Relation注释。
关系实际上并不是在表中定义的(@Entity注释类),它们是独立的,除非您通过使用外键约束来强制引用完整性(子级必须有父级)来另有说明。
如果您想使用关系,那么您可以创建一个可以组合相关表数据的 POJO 类。
您拥有的是类型转换和电影表。 MovieCast 表看起来就是所谓的关联表(映射表、引用表和其他名称)。它迎合了多对多关系。也就是说,一部电影可以有许多相关的 Actor 阵容,而一个 Actor 阵容可以与许多电影相关。
所以对于 MovieWithCastDbModel 你想要类似的东西:-
@Entity(
tableName = "movie_cast",
primaryKeys = ["movieIdMap","castIdMap"],
/* Optional Foreign Key constraints */
foreignKeys = [
/* A MovieId MUST be a value of an existing id column in the movie table */
ForeignKey(
entity = MovieDbModel::class,
parentColumns = ["id"],
childColumns = ["movieIdMap"],
/* Optional (helps maintain referential integrity) */
/* if parent is deleted then children rows of that parent are deleted */
onDelete = ForeignKey.CASCADE,
/* if parent column is changed then the column that references the parent is changed to the same value */
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = CastDbModel::class,
parentColumns = ["id"],
childColumns = ["castIdMap"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class MovieWithCastDbModel(
var movieIdMap: Int,
@ColumnInfo(index = true)
var castIdMap: Int
)
- 可能将其称为 MovieCast 或 MoviesCastMap 而不是 MovieWithCast 更好。
现在,为了允许提取 MoviesWithCast,您需要使用 @Embedded 作为 MovieDbModel 和一个定义关联表的 @Relation 的 POJO。
所以类似:-
data class MovieWithListOfCast(
@Embedded /* The parent */
var movie: MovieDbModel,
@Relation(
entity = CastDbModel::class, /* The class of the related table(entity) (the children)*/
parentColumn = "id", /* The column in the @Embedded class (parent) that is referenced/mapped to */
entityColumn = "id", /* The column in the @Relation class (child) that is referenced (many-many) or references the parent (one(parent)-many(children)) */
/* For the mapping table */
associateBy = Junction(
value = MovieWithCastDbModel::class, /* The class of the mapping table */
parentColumn = "movieIdMap", /* the column in the mapping table that maps/references the parent (@Embedded) */
entityColumn = "castIdMap" /* the column in the mapping table that maps/references the child (@Relation) */
)
)
var castList: List<CastDbModel>
)
如果您在 @Dao 注释的接口(interface)/asbtract 类中有一个函数,例如
@Transaction
@Query("SELECT * FROM movie")
fun getAllMoviesWithCastList(): List<MovieWithListOfCast>
它将检索具有相关 Actor 阵容的所有电影,作为 MovieWithListOfCast 对象列表(每部电影一个)。
Room 使用 MovieWithListOfCast 中的注释来提取所有相关的类型转换。它通过为每部电影运行底层查询来完成此操作,因此应该使用 @transaction。
关于android - 无法在 Room 数据库中建立关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73255805/