Search code examples
functionentityandroid-roomdata-class

Android Room Kotlin: entities with non data classes


Regarding to classes that can/may be used for entities in room whith Kotlin,

  1. Is it mandatory to use data classes? Or could I use 'normal classes', i.e., the ones I use for the 'bussiness logic'
  2. In case data classes are mandatory: can I add functionality to what they have by default? i.e, can I add functions (for whatever taks they may need) to them?

The documentation doesn't say anything about limiting entities to data classes (although each and every code snippet use a data class).

Thanks.


Solution

  • Is it mandatory to use data classes?

    No, you can use either including a mix.

    • data classes are a convenience class

    can I add functionality to what they have by default?

    Yes.

    Perhaps consider the following:-

    @Entity
    class Table1 {
        @PrimaryKey
        var id: Long? = null
        var name: String = ""
        @Ignore
        var notAColumnInTheTable = false
    
        constructor(){}
    
        @Ignore
        constructor(name: String) {
            this.id = null
            this.name = name
            this.notAColumnInTheTable = true
        }
    
        fun getIdAndName(): String {
            return id.toString() + ":" + name
        }
    }
    

    and :-

    @Entity
    data class Table2(
        @PrimaryKey
        var id: Long? = null,
        var name: String,
        @Ignore
        var notAColumnInTheTable: Boolean = false
    ) {
        constructor(name: String) : this( id = null,name = name, notAColumnInTheTable = true)
        fun getIdAndName(): String {
            return id.toString() + ":" + name
        }
    }
    

    basically they are the same.

    Using :-

    @Dao
    abstract class Table1And2Dao {
        @Insert
        abstract fun insert(table1: Table1): Long
        @Insert
        abstract fun insert(table2: Table2): Long
        @Query("SELECT * FROM table1")
        abstract fun getAllFromTable1(): List<Table1>
        @Query("SELECT * FROM table2")
        abstract fun getAllFromTable2(): List<Table2>
    }
    
    • note the use of an abstract class rather than the normally see interface

    along with a suitable @Database annotated class, in this case one that has a function that returns an instance of the built database and for convenience/brevity allows running on the main thread.

    Then using :-

        var db = AppDatabase.getDatabase(this)
        var dao = db.getTable1AndTable2Dao()
    
        dao.insert(Table1("TABLE1_1"))
        dao.insert(Table2("TABLE2_1"))
        for(t1: Table1 in dao.getAllFromTable1()) {
            Log.d("DBINFO","Name is ${t1.name} ID is ${t1.id} NotAColumnInTable is ${t1.notAColumnInTheTable} idandname = ${t1.getIdAndName()}")
        }
        for(t2: Table2 in dao.getAllFromTable2()) {
            Log.d("DBINFO","Name is ${t2.name} ID is ${t2.id} NotAColumnInTable is ${t2.notAColumnInTheTable} idandname = ${t2.getIdAndName()}")
        }
    

    Results in the log including:-

    D/DBINFO: Name is TABLE1_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE1_1
    D/DBINFO: Name is TABLE2_1 ID is 1 NotAColumnInTable is true idandname = 1:TABLE2_1
    

    Via App Inspection :-

    enter image description here

    and :-

    enter image description here