How to pass array elements as separate paramentes to a function

67 views Asked by At

I am using Room DB in which my table has several columns (34 to be exact). I get data in an array (33 size). How can I pass all of the elements of the array to the constructor of the data class which represents the structure of my database table? Since the constructor defines the structure of the table, it requires all of the values as separate parameters

2

There are 2 answers

0
Andrei Naumets On

Room DB will do this for you. There are docs. link

So. You have some @Entity Class.
If it's not a table and you're using some joins or certain columns, just don't set table_name.

@Entity(tableName = "my_entity_table")
data class MyEntity(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    val id: Int = 0,
    ..
    @ColumnInfo(name = "some_data")
    val someData: String
)

You should register it in your database.

@Database(
    entities = [
        MyEntity::class
    ],
    version = 1
)
abstract class MyDB: RoomDatabase() {

    abstract fun myDAO(): MyDAO

}

And create some DAO interface.

@Dao
interface MyDAO {

    // return inserted id
    @Insert
    suspend fun insert(entity: MyEntity): Int

    @Update
    suspend fun update(entity: MyEntity)

    @Delete
    suspend fun delete(entity: MyEntity)

    // It can be nullable
    @Query("SELECT * FROM my_entity_table WHERE id = :id")
    suspend fun getEntityByID(id: Int): MyEntity?

    @Query("SELECT * FROM my_entity_table")
    suspend fun getAll(): List<MyEntity>


    // get data by coroutines Flow. It updates if data change.
    @Query("SELECT * FROM my_entity_table")
    fun getAllFlow(): Flow<List<MyEntity>>

    // some dynamic queries
    @RawQuery
    suspend fun queryRaw(query: SupportSQLiteQuery): List<MyEntity>

}

Init your db

companion object {

    private var INSTANCE: MyDB? = null

    fun get(context: Context): MyDB{
        if (INSTANCE == null) synchronized(this) {
            if (INSTANCE == null) INSTANCE = Room
                .databaseBuilder(context, klass = MyDB::class.java, "my_db")
                .build()
        }
        return INSTANCE!!
    }

}

And have a fun =)

PS. RawQueryes looks like that

suspend fun getMyEntities(
    id: Int? = null,
    someData: String? = null
): List<MyEntity> {
    val builder = StringBuilder()
    val params = ArrayList<Any>()

    builder.append("SELECT * FROM my_entity_table ")
    var i = 0
    if (id != null) i++
    if (someData != null) i++
    //.. more filters
    if (i > 0) builder.append("WHERE ")
    id?.run {
        builder.append("id = ? ")
        params.add(id)
    }
    someData?.run {
        if (params.size > 0) builder.append("AND ")
        builder.append("some_data = ? ")
        params.add(someData)
    }
    return database.myDAO().queryRaw(SimpleSQLiteQuery(builder.toString(), params.toArray()))
}
0
David Soroko On

You can add a secondary constructor to your data class that takes care of the conversion.

For example:

data class Data(val col1: Int, val col2: Int, val col3: Int) {
    constructor(values: List<Int>): this(values[0], values[1],values[2])
}

fun main() {
    Data(listOf(1,2,3,4))
        .also { println(it) } //Data(col1=1, col2=2, col3=3)
}