&引用;没有这样的专栏“;Android Room和POJO上多个@Embedded字段的SQL错误
原始问题位于最底部。我为我的问题创建了一个最小的(非)工作示例,希望更容易阅读。例子是。有一份自述文件描述了这个问题。我在这里粘贴项目的一些部分 数据模型非常简单:&引用;没有这样的专栏“;Android Room和POJO上多个@Embedded字段的SQL错误,android,android-room,Android,Android Room,原始问题位于最底部。我为我的问题创建了一个最小的(非)工作示例,希望更容易阅读。例子是。有一份自述文件描述了这个问题。我在这里粘贴项目的一些部分 数据模型非常简单: Owner <--(1:N)-- Child --(N:1)--> ReferencedByChild 构建此代码导致此错误消息: error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no suc
Owner <--(1:N)-- Child --(N:1)--> ReferencedByChild
构建此代码导致此错误消息:
error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: refByChildId)
我认为Owner
查询构造得很糟糕,但我不能完全确定。如果这就是问题所在,那么构造查询的正确方法是什么
这是原始问题 我有一个嵌套的POJO结构,它应该表示一个
游戏
有多个回合
,每个回合
都有一个与之关联的主题
:
class GameWithRounds {
@Embedded
var game: Game? = null
@Relation(
parentColumn = "id",
entityColumn = "gameId",
entity = RoundRoom::class
)
var rounds: List<RoundWithTopic>? = null
}
class RoundWithTopic(
@Embedded
var round: RoundRoom,
@Embedded(prefix = "topic_")
var topic: Topic
)
但是,构建项目会给我带来房间错误:
There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: topic_id)
即使当我提出关于哪些字段实际存在的警告时,Room告诉我:
Columns returned by the query: topic_id, topic_name, topic_description, topic_language, topic_keywords, topic_sourceUrls, topic_furtherUrls, topic_questions, order, gameId, topicId, status, id. Fields in cz.melkamar.sklapecka.model.RoundWithTopic: order, gameId, topicId, status, id, topic_id, topic_name, topic_description, topic_language, topic_keywords, topic_sourceUrls, topic_furtherUrls, topic_questions, topic_image.
查询结果中有topic\u id
列!为什么我会犯这个错误
为完整起见,这是实体:
@Entity
data class Game(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded
val gameConfigurationEmbed: GameConfigurationEmbed
)
data class GameConfigurationEmbed(
var secondsPerTurn: Int,
var maxSecondsPerTurn: Int,
var bonusSecondsPerAnswer: Int
)
@Entity(
foreignKeys = [
ForeignKey(
entity = Game::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("gameId"),
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Topic::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("topicId"),
onDelete = ForeignKey.CASCADE
)
]
)
@TypeConverters(RoomConverters::class)
data class RoundRoom(
val order: Int,
var gameId: Long,
val topicId: String,
var status: RoundStatus = RoundStatus.CREATED,
@PrimaryKey(autoGenerate = true)
val id: Long = 0
) {
enum class RoundStatus {
CREATED, UPCOMING, IN_PROGRESS, FINISHED
}
}
@Entity
data class Topic(
@PrimaryKey val id: String,
val name: String,
val description: String,
val language: String,
val keywords: List<String>,
val sourceUrls: List<String>,
val furtherUrls: List<String>,
val questions: List<String>,
val image: ByteArray?
)
@实体
数据类游戏(
@PrimaryKey(自动生成=真)
val id:Long=0,
@嵌入
val gameConfigurationEmbed:gameConfigurationEmbed
)
数据类GameConfigurationEmbedded(
变量secondsPerTurn:Int,
var maxSecondsPerTurn:Int,
var bonusSecondsPerAnswer:Int
)
@实体(
外键=[
外侨(
实体=游戏::类,
parentColumns=arrayOf(“id”),
childColumns=arrayOf(“gameId”),
onDelete=ForeignKey.CASCADE
),
外侨(
实体=主题::类,
parentColumns=arrayOf(“id”),
childColumns=arrayOf(“topicId”),
onDelete=ForeignKey.CASCADE
)
]
)
@类型转换器(RoomConverters::class)
数据类会议室(
val顺序:Int,
配子体:长,
val-topicId:String,
变量状态:RoundStatus=RoundStatus.CREATED,
@PrimaryKey(自动生成=真)
val id:Long=0
) {
枚举类状态{
已创建、即将发布、正在进行、已完成
}
}
@实体
数据类主题(
@PrimaryKey值id:字符串,
val name:String,
val说明:字符串,
val语言:String,
val关键字:列表,
val sourceurl:List,
val:url列表,
val问题:列表,
val图像:ByteArray?
)
经过一些研究,特别是查看以下链接:
我们找到的唯一答案是
经过一些研究,特别是查看此链接: 我们找到的唯一答案是
似乎嵌入式字段和类型转换器在观察问题时没有正确使用。我不想详细讨论这个问题的解决方案,因为它试图使用复杂的关系,我无法在我的机器上测试它的复制 但我想提供有关使用嵌入式字段和类型转换器的见解 让我们以上面的问题为例: 游戏表中有字段
id、secondsPerTurn、maxSecondsPerTurn、bonusSecondsPerAnswer
可以创建如下所示的实体
@Entity
data class Game(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded
val gameConfigurationEmbed: GameConfigurationEmbed
)
data class GameConfigurationEmbed(
var secondsPerTurn: Int,
var maxSecondsPerTurn: Int,
var bonusSecondsPerAnswer: Int
)
在SQLite表中,数据实际上存储在四个不同的列中,但是Room基于数据类结构执行CRUD操作,这为开发人员提供了更高的可行性
类型转换器
如果我们想要存储非基本数据类型或@嵌入式
不包含的相同类型的数据,类型转换器将非常有用
例如,足球比赛可以在两个地方举行:主场和客场。Home和Away可以具有相同的字段名,如地名、纬度、经度
。在这种情况下,我们可以创建数据类和类型转换器,如下所示:
data class GamePlace(
val placeName:String,
val latitude:String,
val longitude:String
)
@Entity
data class Game(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded
val gameConfigurationEmbed: GameConfigurationEmbed
@TypeConverters
var home: GamePlace? = null,
@TypeConverters
var away: GamePlace? = null,
)
object Converters {
private val gson = Gson()
@TypeConverter
@JvmStatic
fun fromGamePlace(gamePlace: GamePlace?): String? {
return if (gamePlace == null) null else gson.toJson(gamePlace)
}
@TypeConverter
@JvmStatic
fun toGamePlace(jsonData: String?): GamePlace? {
return if (jsonData.isNullOrEmpty()) null
else gson.fromJson(jsonData, object : TypeToken<GamePlace?>() {}.type)
}
}
我希望这将有助于处理和解决这个问题。在观察这个问题时,似乎没有正确使用嵌入式字段和类型转换器。我不想详细讨论这个问题的解决方案,因为它试图使用复杂的关系,我无法在我的机器上测试它的复制 但我想提供有关使用嵌入式字段和类型转换器的见解 让我们以上面的问题为例: 游戏表中有字段
id、secondsPerTurn、maxSecondsPerTurn、bonusSecondsPerAnswer
可以创建如下所示的实体
@Entity
data class Game(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded
val gameConfigurationEmbed: GameConfigurationEmbed
)
data class GameConfigurationEmbed(
var secondsPerTurn: Int,
var maxSecondsPerTurn: Int,
var bonusSecondsPerAnswer: Int
)
在SQLite表中,数据实际上存储在四个不同的列中,但是Room基于数据类结构执行CRUD操作,这为开发人员提供了更高的可行性
类型转换器
如果我们想要存储非基本数据类型或@嵌入式
不包含的相同类型的数据,类型转换器将非常有用
例如,足球比赛可以在两个地方举行:主场和客场。Home和Away可以具有相同的字段名,如地名、纬度、经度
。在这种情况下,我们可以创建数据类和类型转换器,如下所示:
data class GamePlace(
val placeName:String,
val latitude:String,
val longitude:String
)
@Entity
data class Game(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@Embedded
val gameConfigurationEmbed: GameConfigurationEmbed
@TypeConverters
var home: GamePlace? = null,
@TypeConverters
var away: GamePlace? = null,
)
object Converters {
private val gson = Gson()
@TypeConverter
@JvmStatic
fun fromGamePlace(gamePlace: GamePlace?): String? {
return if (gamePlace == null) null else gson.toJson(gamePlace)
}
@TypeConverter
@JvmStatic
fun toGamePlace(jsonData: String?): GamePlace? {
return if (jsonData.isNullOrEmpty()) null
else gson.fromJson(jsonData, object : TypeToken<GamePlace?>() {}.type)
}
}
我希望这将有助于t
@Database(
entities = [Game::class /* ,more classes here*/],
version = 1
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun gameDao(): GameDao
//.....
}