Android 成功设计room数据库模式后,如何获取作为网络响应中另一条记录的一部分的记录列表 我正在努力实现的目标
我正在开发一个天气预报应用程序,它有足够的空间作为本地缓存数据库,用于我从OpenWeatherMapAPI获得的json响应,如下所示Android 成功设计room数据库模式后,如何获取作为网络响应中另一条记录的一部分的记录列表 我正在努力实现的目标,android,kotlin,database-design,android-sqlite,android-room,Android,Kotlin,Database Design,Android Sqlite,Android Room,我正在开发一个天气预报应用程序,它有足够的空间作为本地缓存数据库,用于我从OpenWeatherMapAPI获得的json响应,如下所示 { "cod":"200", "message":0, "cnt":40, "list":[ { "dt":1590602400, "main":{ "temp":306.2, "feels_like":306.4,
{
"cod":"200",
"message":0,
"cnt":40,
"list":[
{
"dt":1590602400,
"main":{
"temp":306.2,
"feels_like":306.4,
"temp_min":306.07,
"temp_max":306.2,
"pressure":1006,
"sea_level":1004,
"grnd_level":950,
"humidity":41,
"temp_kf":0.13
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03n"
}
],
"clouds":{
"all":48
},
"wind":{
"speed":3.72,
"deg":183
},
"sys":{
"pod":"n"
},
"dt_txt":"2020-05-27 18:00:00"
},
{
"dt":1590613200,
"main":{
"temp":305.05,
"feels_like":303.65,
"temp_min":304.7,
"temp_max":305.05,
"pressure":1004,
"sea_level":1003,
"grnd_level":949,
"humidity":38,
"temp_kf":0.35
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04n"
}
],
"clouds":{
"all":68
},
"wind":{
"speed":4.72,
"deg":197
},
"sys":{
"pod":"n"
},
"dt_txt":"2020-05-27 21:00:00"
},
{
"dt":1590624000,
"main":{
"temp":302.97,
"feels_like":304.29,
"temp_min":302.74,
"temp_max":302.97,
"pressure":1004,
"sea_level":1004,
"grnd_level":949,
"humidity":46,
"temp_kf":0.23
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03n"
}
],
"clouds":{
"all":47
},
"wind":{
"speed":1.48,
"deg":196
},
"sys":{
"pod":"n"
},
"dt_txt":"2020-05-28 00:00:00"
}
],
"city":{
"id":1269843,
"name":"Hyderabad",
"coord":{
"lat":17.3753,
"lon":78.4744
},
"country":"IN",
"population":3597816,
"timezone":19800,
"sunrise":1590538296,
"sunset":1590585318
}
}
基于json响应,我为room模式提供了以下数据类
Record.class
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
天气。班级
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
天气记录类
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
class天气记录(
@嵌入
val记录:记录,
@关系(parentColumn=“rid”,entityColumn=“wid”)
瓦尔天气:列表
)
还有其他的课程,如雨、雨、风、城市等等
现在我要上的反应课是
WeatherResponse.class
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
数据类天气响应(
瓦尔城:城市,
val cnt:Int,
瓦尔·科德:字符串,
val列表:列表,
val消息:Int
)
我到现在为止都做了些什么
根据JSON响应,可以很容易地理解Weather应该是Record类中的一个字段,但它不在那里,这是因为Weather作为一个列表出现,因为我使用了外键和一些小技巧(如下面的答案()所述)在我的Dao查询中,以存储列表并在数据库中获取天气列表
Dao类
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
@Dao
接口WetherDataDao{
@插入(onConflict=OnConflictStrategy.REPLACE)
fun upsert(数据:记录)
@插入
趣味插页(天气:列表)
@交易
趣味插页(weatherRecord:weatherRecord){
向上插入(天气记录,记录)
插入(weatherRecord.weather)
}
@查询(“从记录中选择*)
fun getAllRecords():LiveData
}
我有什么问题
因此,在实施该房间之前,我得到了正确的响应(即天气将作为记录的一部分),但在这之后,我不会将天气作为记录的一部分,也不会在其他任何地方得到。
我试图通过在WeatherRecord类中将列表类型从Record更改为WeatherRecord来解决问题,但这也没有解决我的问题(只是用一些代码打印了类的路径,请参阅屏幕截图)所以,有谁能帮我解决这个问题吗?你可以建议我任何其他可能改变整个数据库设计模式的解决方案,我愿意学习
因为我是新手,所以您可以向我推荐一些有趣的博客,介绍如何为这种复杂的数据库设计数据库模式
提前谢谢我不知道我的回答是否有用。它更多的是关于原则,而不是实际的指导 一些思考
@Entity(tableName = "Record")
data class Record(
@PrimaryKey(autoGenerate = true)
val rid:Long,
@SerializedName("dt_txt")
val dtTxt: String,
@Embedded(prefix = "main_")
val main: Main,
@Embedded(prefix = "rain_")
val rain: Rain,
@Embedded(prefix = "wind_")
val wind: Wind
)
@Entity(
tableName = "weather",
foreignKeys = [
ForeignKey(
entity = Record::class,
parentColumns = ["rid"],
childColumns = ["wid"],
onDelete = CASCADE
)
])
data class Weather(
@PrimaryKey(autoGenerate = true)
val wid:Long,
val description: String,
val icon: String,
val id: Int,
val main: String
)
class WeatherRecord (
@Embedded
val record: Record,
@Relation(parentColumn = "rid", entityColumn = "wid")
val weather:List<Weather>
)
data class WeatherResponse(
val city: City,
val cnt: Int,
val cod: String,
val list: List<Record>,
val message: Int
)
@Dao
interface WetherDataDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun upsert(data: Record)
@Insert
fun insert(weather:List<Weather>)
@Transaction
fun insert(weatherRecord: WeatherRecord){
upsert(weatherRecord.record)
insert(weatherRecord.weather)
}
@Query("Select * from Record")
fun getAllRecords():LiveData<WeatherRecord>
}
应用程序中有几种类型的数据类组:
- “传输”组。此组的结构由传输接口组成。例如,您有Android应用程序,并且有后端。您有一些JSON协议,您决定使用改型,因此为了以适当的形式获取数据,您必须根据JSON结构构建类
- “数据库”组。该组的结构并不严格,但如果使用关系数据库(SQLite就是其中之一),则必须遵循一些要求。例如,不能将另一个对象用作表的字段(只使用外键),等等
- “业务逻辑”组。该组的结构几乎没有限制,它必须高效地用于应用程序逻辑的核心
- 根据JSON,您必须为“Transfer”组构建特定的数据类集(我认为这是最明显的部分)
- 要持久化数据,有几种选择。这取决于你的应用程序的使用情况。例如,这里不要求将“wind”保存到单独的表中(与相应的“Transfer”数据类相关联)。如果这样做有意义,你可以这样做。但你也可以在这里选择最简单的模型-只有两个表“main_data”(除天气模块外的所有数据)和“附加天气模块数据”(仅带外键的天气模块到主天气模块表)比如说,你已经有了Wind、Rain的改造列表,并且你在SQLite中只有一个main_表可以保存这些数据列表。但这不是问题——在你房间的DAO中应该有一些函数,可以保存你想要保存在main_表中的所有数据
- 对于您的用例,您可以声明其他具有对您有效的结构的类(可能有些类与您的“传输”数据类相同,也可能不同)。您是否需要单独使用“风”或“雨”——好吧,这没有问题。您声明您的类并在Room DAO的请求中将其用作返回值的类型(一个SQLite表中有两个单独的函数)。您可以将这些类和对象列表声明为类的字段,Room可以使用
.非常感谢@sergiy tikhonov,你对这个概念解释得很好,我的问题得到了解决