【问题标题】:How to pre-populate Room Database with array of Strings如何使用字符串数组预填充房间数据库
【发布时间】:2021-11-18 14:59:26
【问题描述】:

我正在尝试创建一个包含字符串数组的 Room 数据库,并希望进行预填充。我为 SQLite 尝试了 db browser,但它不包含数组数据类型。我能做些什么? 我添加了我的表格模型和类型转换器。

@Entity(tableName ="Data Table")
data class Datas(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "Id")
    val id : Int ,
    @ColumnInfo(name = "Data1")
    val data1 : String ,
    @ColumnInfo(name = "Data2")
    val data2 : Array<String> ,
    @ColumnInfo(name = "Data3")
    val data3 : Array<String>,
    @ColumnInfo(name = "Data4")
    val data4 : Array<String>,
    @ColumnInfo(name = "Data5")
    val data5 : Array<String>,



    )
    class converter{
    @TypeConverter
    fun fromString(value : String) : Array<String> {
        val listType = object : TypeToken<ArrayList<String>>(){}.type
        return Gson().fromJson(value,listType)
    }
    @TypeConverter
    fun fromArrayList(list : Array<String?>) : String {
        return Gson().toJson(list)

    }
}

【问题讨论】:

    标签: android sqlite kotlin android-room


    【解决方案1】:

    简而言之,实际存储的数据相对复杂,通过 Db 浏览器手动输入可能很困难或令人沮丧。

    例如考虑值是的单个条目:

    data1 是 D1 数据2是A,B data3 是 C,D,E data4 是 F,G,H,I,J,K data5 为 L,M,N,O

    这实际上是使用 GSON 存储的,类似于(虽然不完全是):-

    • 将解释 sa 部分,因为上面来自一个工作示例。

    但是,我认为您的代码存在问题。我相信,你不能有一个列(例如 data2)是一个列表/数组,该列必须是一个类(可能包含一个列表)。

    • TypeConverters 似乎无法处理数组/列表。

    你会得到一个编译器错误:-

    error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    private final java.lang.String[] data2 = null;
                                     ^
    

    所以为了演示(上面的数据来自哪里)创建了一个类来嵌入数组:-

    data class StringArray(
        var sa: Array<String>
    )
    
    • 这就是 sa 的来源。
    • 显然可以使用适合的名称。

    那么你可以让数据成为:-

    @Entity(tableName ="Data Table")
    data class Datas(
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "Id")
        val id : Int,
        @ColumnInfo(name = "Data1")
        val data1 : String = "",
        @ColumnInfo(name = "Data2")
        var data2: StringArray,
        @ColumnInfo(name = "Data3")
        var data3 : StringArray,
        @ColumnInfo(name = "Data4")
        var data4 : StringArray,
        @ColumnInfo(name = "Data5")
        var data5 : StringArray
        )
    

    然后转换器类将/可能是:-

    class converter {
    
        @TypeConverter
        fun fromString(value: String): List<String> {
            val listType = object : TypeToken<ArrayList<String>>() {}.type
            return Gson().fromJson(value, listType)
        }
    
        @TypeConverter
        fun fromArrayList(list: List<String>): String {
            return Gson().toJson(list)
        }
    
    
        /* Replacement Converters */
        @TypeConverter
        fun fromJSONStringToStringArray(value: String): StringArray {
            val listType = object : TypeToken<StringArray>() {}.type
            return Gson().fromJson(value,listType)
            /* or just the single line :- that follows */
            // return Gson().fromJson(value, StringArray::class.java)
        }
    
        @TypeConverter
        fun fromStringArrayToJSONString(list: StringArray): String {
            return Gson().toJson(list)
        }
    }
    
    • 原件留作比较

    因此,您可以使用您的数据库(可能在不同的应用程序中纯粹用于生成数据)来实际创建数据库(这会更容易)或生成要复制并粘贴到 Db 中的数据浏览器正在做一些事情:-

    对于演示,创建了一个 SourceData 类:-

    /* The data to pre-populate the database */
    class SourceData {
        companion object {
    
            val d1: Datas = Datas(
                id = 0,
                data1 = "D1",
                data2 = StringArray(arrayOf("A","B")),
                data3 = StringArray(arrayOf("C","D","E")),
                data4 = StringArray(arrayOf("F","G","H","I","J","K")),
                data5 = StringArray(arrayOf("L","M","N","O"))
            )
            val d2: Datas = Datas(
                id = 0,
                data1 = "D1",
                data2 = StringArray(arrayOf("AA","AB","AC")),
                data3 = StringArray(arrayOf("AD","AE")),
                data4 = StringArray(arrayOf("AF","AG","AH","AI","AJ","AK")),
                data5 = StringArray(arrayOf("AL","AM","AN","AO"))
            )
            val d3: Datas = Datas(
                id = 0,
                data1 = "D1",
                data2 = StringArray(arrayOf("BA","BB","BC")),
                data3 = StringArray(arrayOf("BD","BE")),
                data4 = StringArray(arrayOf("BF","BG","BH","BI","BJ","BK")),
                data5 = StringArray(arrayOf("BL","BM","BN","BO"))
            )
    
            val all: List<Datas> = listOf(d1,d2,d3)
        }
    }
    
    • 不是最容易使用,但比尝试手动创建 JSON 更容易。
    • 现在是 3 行数据。

    插入的@Dao 类:-

    @Dao
    abstract class AllDao {
        @Insert
        abstract fun insert(datas: Datas): Long
        @Insert
        abstract fun insert(vararg datas: Datas): Array<Long>
        @Insert
        abstract fun insert(datasList: List<Datas>): Array<Long>
    
    }
    
    • 第一个将插入一行
    • 第二个将插入 1 个或多个,例如insert(d1,d2,d3)
    • 第三个需要一个列表

    您将需要一个包含 @TypeConverters 注释的 @Database 类,该注释指定转换器类,例如:-

    @Database(entities = [Datas::class],version = 1)
    @TypeConverters(converter::class)
    abstract class TheDatabase: RoomDatabase() {
        abstract fun getAllDao(): AllDao
    
        companion object {
    
            @Volatile
            private var instance: TheDatabase? = null
            fun getInstance(context: Context): TheDatabase {
                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context,
                        TheDatabase::class.java,
                        "my.db"
                    )
                        .allowMainThreadQueries()
                        .build()
                }
                return instance as TheDatabase
            }
        }
    }
    
    • 注意allowMainThreadQueries 用于方便和简洁

    最后是一个 Activity,在这种情况下,它使用 fromStringArrayToJSONString TypeConverter 输出 JSON,可以将其复制并粘贴到 DB 浏览器中,甚至可以重新调整以作为文件导入(我猜(我只是创建数据库并复制数据库文件))。

    class MainActivity : AppCompatActivity() {
    
        lateinit var db: TheDatabase
        lateinit var dao: AllDao
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            db = TheDatabase.getInstance(this)
            dao = db.getAllDao()
    
            dao.insert(all)
            logWhatConverterStores(d1)
            logWhatConverterStores(d2)
            logWhatConverterStores(d3)
    
            }
        }
    
        fun logWhatConverterStores(d: Datas) {
            logAD(d.data2)
            logAD(d.data3)
            logAD(d.data4)
            logAD(d.data5)
        }
    
        private fun logAD(aD: StringArray) {
            Log.d("CONVERTED","Converted/Stored as ${converter().fromStringArrayToJSONString(aD)}")
        }
    
    }
    

    运行上述程序会生成一个数据库(通过 Android Studio 的 App Inspection):-

    日志中的一个:-

    2021-09-26 21:23:40.002 Converted/Stored as {"sa":["A","B"]}
    2021-09-26 21:23:40.003 Converted/Stored as {"sa":["C","D","E"]}
    2021-09-26 21:23:40.007 Converted/Stored as {"sa":["F","G","H","I","J","K"]}
    2021-09-26 21:23:40.008 Converted/Stored as {"sa":["L","M","N","O"]}
    2021-09-26 21:23:40.010 Converted/Stored as {"sa":["AA","AB","AC"]}
    2021-09-26 21:23:40.012 Converted/Stored as {"sa":["AD","AE"]}
    2021-09-26 21:23:40.012 Converted/Stored as {"sa":["AF","AG","AH","AI","AJ","AK"]}
    2021-09-26 21:23:40.014 Converted/Stored as {"sa":["AL","AM","AN","AO"]}
    2021-09-26 21:23:40.015 Converted/Stored as {"sa":["BA","BB","BC"]}
    2021-09-26 21:23:40.016 Converted/Stored as {"sa":["BD","BE"]}
    2021-09-26 21:23:40.017 Converted/Stored as {"sa":["BF","BG","BH","BI","BJ","BK"]}
    2021-09-26 21:23:40.017 Converted/Stored as {"sa":["BL","BM","BN","BO"]}
    

    【讨论】:

      【解决方案2】:

      也许是一个肮脏的解决方案,但我会:

      1. 编写一个方法,将你想要的字符串保存到数据库中
      2. 在模拟器中运行应用并执行该方法
      3. 从模拟器中检索数据库

      繁荣:预填充数据库

      如果您想手动执行此操作,您可以将字符串列表转换为与Gson().toJson() 输出的格式相同的 json,然后将其粘贴到 sqlite 浏览器中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-22
        • 2021-12-28
        相关资源
        最近更新 更多