Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 成功设计room数据库模式后,如何获取作为网络响应中另一条记录的一部分的记录列表 我正在努力实现的目标_Android_Kotlin_Database Design_Android Sqlite_Android Room - Fatal编程技术网

Android 成功设计room数据库模式后,如何获取作为网络响应中另一条记录的一部分的记录列表 我正在努力实现的目标

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,

我正在开发一个天气预报应用程序,它有足够的空间作为本地缓存数据库,用于我从OpenWeatherMapAPI获得的json响应,如下所示

{
   "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就是其中之一),则必须遵循一些要求。例如,不能将另一个对象用作表的字段(只使用外键),等等

  • “业务逻辑”组。该组的结构几乎没有限制,它必须高效地用于应用程序逻辑的核心

在简单的Android应用程序中,所有3个数据组都可以使用相同的数据类集来实现,在复杂的应用程序中,它们可能会因彼此之间的某种映射而有所不同。每个公司都可以指定某种模式来构建类的层次结构。因此,我始终认为这里没有灵丹妙药

在实践中

  • 根据JSON,您必须为“Transfer”组构建特定的数据类集(我认为这是最明显的部分)
  • 要持久化数据,有几种选择。这取决于你的应用程序的使用情况。例如,这里不要求将“wind”保存到单独的表中(与相应的“Transfer”数据类相关联)。如果这样做有意义,你可以这样做。但你也可以在这里选择最简单的模型-只有两个表“main_data”(除天气模块外的所有数据)和“附加天气模块数据”(仅带外键的天气模块到主天气模块表)比如说,你已经有了Wind、Rain的改造列表,并且你在SQLite中只有一个main_表可以保存这些数据列表。但这不是问题——在你房间的DAO中应该有一些函数,可以保存你想要保存在main_表中的所有数据
  • 对于您的用例,您可以声明其他具有对您有效的结构的类(可能有些类与您的“传输”数据类相同,也可能不同)。您是否需要单独使用“风”或“雨”——好吧,这没有问题。您声明您的类并在Room DAO的请求中将其用作返回值的类型(一个SQLite表中有两个单独的函数)。您可以将这些类和对象列表声明为类的字段,Room可以使用

.

非常感谢@sergiy tikhonov,你对这个概念解释得很好,我的问题得到了解决