I am building a simple weight tracking app in Kotlin, using room, and am having a tough time finding the resource to figure out how to query and return just the one value from the database without it returning my entire data class.
I realize I am returning a list in my Dao, but can someone explain to me how to return just the minimum weight without the list?
I am still fairly new to room so any help is appreciated
my Dao
@Dao
interface WeightDao {
@Query("SELECT * FROM weight")
fun getAllWeightEntries():Flow<List<Weight>>
This does returns the lowest weight entry but includes everything else from my data class
@Query("SELECT * FROM weight WHERE weight_entry = (SELECT MIN(weight_entry) FROM weight)")
fun getLowestWeightEntry():Flow<List<Weight>>
My dataclass
@Entity(tableName = "weight")
data class Weight(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "weight_entry")
val weightEntry: Double,
@ColumnInfo(name = "weight_entry_notes")
val weightEntryNotes: String
)
Snippet from my viewmodel
val lowestWeightEntry: LiveData<List<Weight>> = weightDao.getLowestWeightEntry().asLiveData()
snippet from my u.i. fragment
viewModel.lowestWeightEntry.observe(this.viewLifecycleOwner) { item ->
item.let {
binding.tvLowestWeightTest.text = item.toString()
}
}
I believe that you could use the following:-
@Query("SELECT min(weight_entry) FROM weight")
fun getAllWeightEntries():Flow<Double>
That is, if the output is a single column you can use the appropriate type for that value (as long as it's one of the types that Room supports directly for a column (i.e. no TypeConverter required)).
And obviously the viewmodel should expect to retrieve that type of value.
A Little more on the subject (POJO's for non @Entity types)
For anything other than a single value, other than for an @Entity
annotated class that is defined in the entries
parameter of the @Database
annotation (which tells Room that the class is a table) then you need a POJO whose field names match the output field names.
e.g. say you had
@Query("SELECT min(weight_entry) AS min, max(weight_entry) AS max FROM weight")
fun getAllWeightEntries():Flow<weightMinAndMax>
The you could have a POJO such as:-
data class weightMinAndMax(
val min: Double,
val max: Int /* although should be Double */
)
AS
gives the output column an alias (min and max respectively) to suit the POJO fields (else output columns would be min(weight_entry) and max(weight_entry) respectively).name
parameter of the @ColumnInfo to override the expected output column namee.g. you could have
@Query("SELECT min(weight_entry) AS mymin, max(weight_entry) AS mymax FROM weight")
fun getAllWeightEntries():Flow<weightMinAndMax>
The you could have a POJO such as:-
data class weightMinAndMax(
@ColumnInfo(name = "mymin")
val min: Double,
@ColumnInfo(name = "mymax")
val max: Int /* although should be Double */
)
In Short; for a single value output from a Query Room does not need to match output columns with field names. For multiple value outputs from a Query then Room needs to be able to associate the output values with the respective fields in the recipient object.