Home > other >  How to pre-populate Room Database with array of Strings
How to pre-populate Room Database with array of Strings

Time:09-27

I am trying to create a Room database that contains array of strings and want to do that pre-populated. I tried db browser for SQLite, but it does not contain array data type. What can I do? I added my table model and type converters.

@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)

    }
}

CodePudding user response:

Maybe a dirty solution, but I'd:

  1. write a method that saves the strings you want to the database
  2. run the app in an emulator and execute that method
  3. retrieve the db from the emulator

boom pre-populated db

If you want to do it manually, you could convert your list of strings to json in the same format outputted by Gson().toJson() and paste that into sqlite browser

CodePudding user response:

In short the data actually stored is relatively complex and may be difficult or frustrating to input manually via Db Browser.

For example consider a single entry where the values are :

data1 is D1 data2 is A,B data3 is C,D,E data4 is F,G,H,I,J,K data5 is L,M,N,O

this would actually be stored, using GSON, something like (not exactly though) :-

enter image description here

  • the sa part will be explained, as the above is from a working example.

However I believe that you have an issue with your code as it is. You cannot, I believe, have a column (such as data2) that is a list/array, the column has to be a single class (which may hold a list).

  • The TypeConverters do not appear to be able to handle arrays/lists.

You would get a compiler error along the lines of :-

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;
                                 ^

So for the demonstration (where the data above came from) a class was created to embed the Array :-

data class StringArray(
    var sa: Array<String>
)
  • this is where the sa comes from.
  • obviously names to suit could be used.

Then you could have Datas being :-

@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
    )

and the converter class would/could then be :-

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)
    }
}
  • originals have been left in for comparison

So what you can do is with your database (perhaps in a different App purely for the generation of the data), to either actually create the database (this would be easier) or generate the data to be copied and pasted into Db Browser is do something along the lines of :-

For the demo a SourceData class was created as:-

/* 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)
    }
}
  • not the easiest to work with BUT easier than trying to manually create the JSON.
  • so now 3 rows of data.

An @Dao class for the inserts :-

@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>

}
  • the first will insert a single row
  • the second will insert 1 or more e.g. insert(d1,d2,d3)
  • the third takes a List

you will need an @Database class that includes an @TypeConverters annotation that specifies the converter(s) class(es) e.g. :-

@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
        }
    }
}
  • note allowMainThreadQueries used for convenience and brevity

Finally an Activity, and in this case one which, uses the fromStringArrayToJSONString TypeConverter to output the JSON which could be copied and pasted into DB Browser or even rejigged to be imported as a file (I guess (I would just create the database and copy the database file)).

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)}")
    }

}

Running the above produces a database (via Android Studio's App Inspection) :-

enter image description here

An in the log :-

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"]}
  • Related