Partial Entities
Prior to the introduction of support for SQL default values, we always had to provide values for all columns in our INSERT
statements. If you inserted solely via @Insert
, you might not notice this limitation. The fact that we now have SQL default value support means that the “insert-by-@Query
” option has greater flexibility: we do not have to provide all values for all columns.
Related to that is partial entity support, where we can have ordinary @Insert
DAO functions also only supply a subset of properties to go into the to-be-inserted row.
We covered earlier in the book how we can use arbitrary POJOs or Kotlin data classes for the output of @Query
functions:
package com.commonsware.room.misc
import androidx.room.*
import kotlin.random.Random
data class CountAndSumResult(val count: Int, val sum: Long)
@Entity(tableName = "aggregate")
class AggregateEntity(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val value: Long = Random.nextLong(1000000)
) {
@Dao
interface Store {
@Query("SELECT * FROM aggregate")
fun loadAll(): List<AggregateEntity>
@Query("SELECT COUNT(*) FROM aggregate")
fun count(): Int
@Query("SELECT COUNT(*) as count, SUM(value) as sum FROM aggregate")
fun countAndSum(): CountAndSumResult
@Insert
fun insert(entities: List<AggregateEntity>)
}
}
Here, we use CountAndSumResult
to model the response from:
SELECT COUNT(*) as count, SUM(value) as sum FROM aggregate
Similarly, we can use a POJO or Kotlin data class to model partial input to an @Insert
, @Update
, or @Delete
function:
package com.commonsware.room.misc
import androidx.room.*
data class PartialDefaultValue(
val id: String,
val title: String
)
@Entity(tableName = "defaultValue")
class DefaultValueEntity(
@PrimaryKey
val id: String,
val title: String,
@ColumnInfo(defaultValue = "something")
val text: String? = null,
@ColumnInfo(defaultValue = "123")
val version: Int = 1
) {
@Dao
interface Store {
@Query("SELECT * FROM defaultValue")
fun loadAll(): List<DefaultValueEntity>
@Query("SELECT * FROM defaultValue where id = :id")
fun findByPrimaryKey(id: String): DefaultValueEntity
@Insert
fun insert(entity: DefaultValueEntity)
@Query("INSERT INTO defaultValue (id, title) VALUES (:id, :title)")
fun insertByQuery(id: String, title: String)
@Insert(entity = DefaultValueEntity::class)
fun insertPartial(partial: PartialDefaultValue)
}
}
In addition to the insert()
and insertByQuery()
DAO functions, we have insertPartial()
. This accepts a PartialDefaultValue
object and uses that for an INSERT
into our table.
By default, this would fail at compile time, with the Room annotation processor complaining that PartialDefaultValue
is not an entity. However, on the @Insert
annotation for insertPartial()
, we use an entity
property to teach Room what @Entity
is associated with this @Insert
operation:
@Insert(entity = DefaultValueEntity::class)
fun insertPartial(partial: PartialDefaultValue)
The POJO or Kotlin data class that you supply as input (PartialDataEntity
) will be used like the entity itself, based on individual property names. Room will look in the supplied object for properties matching those of the entity class and use the ones that it finds. For everything else — such as text
and version
in this case — Room will rely on the underlying table either supporting NULL
for the column… or having a defaultValue
supplied.
Many developers will not need these features. Kotlin property default values and an ordinary @Insert
will suffice. But, these features make it a bit easier to model classic SQL database structures and may help in some scenarios.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.