How to get last inserted row id using room android kotlin? - android

I want to get the last row id in room android using kotlin
here is my Entity
#Entity(tableName = "tb_customer")
data class Customer(
#PrimaryKey(autoGenerate = true)
var customerId: Long = 0L,
val firstName: String,
val lastName: String,
val emailAddress: String,
val address: String,
val profileImage: String?)
my Dao
#Dao
interface CustomerDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(customer: Customer): Long
#Insert
suspend fun insertPhones(customerPhones: ArrayList<CustomerPhones>)
#Delete
suspend fun delete(customer: Customer)
#Update
suspend fun update(customer: Customer)
#Query("SELECT * FROM tb_customer ORDER BY customerId ASC")
fun getAllCustomers(): LiveData<List<Customer>>
#Query("DELETE FROM tb_customer")
suspend fun clear()
}
**Please help me to get last inserted id **

I have found the answer you could try this code
Dao
#Query("SELECT customerId FROM tb_customer ORDER BY customerId DESC LIMIT 1")
fun getLastCustomer(): LiveData<Long>
a**nd this is the repository **
fun getLastCustomer(): LiveData<Long> {
return customerDao.getLastCustomer()
}
and this is the view model
fun getLastCustomer(): LiveData<Long> {
return repository.getLastCustomer()
}
and finally from your context your have to write
customerViewModel.getLastCustomer().observe(viewLifecycleOwner,{id->
Log.d("TAG ", id.toString())
})

Related

Not sure how to convert a Cursor to this method's return type in Room Android?

I am getting the following error when I build my application
Not sure how to convert a Cursor to this method's return type (kotlinx.coroutines.flow.Flow<? extends java.util.List<com.notification.NotificationEntity>>)
This is my Entity class
#Entity
internal data class NotificationEntity(
#PrimaryKey #ColumnInfo(name = "notification_id") val notificationId: String,
val title: String,
val body: String?,
#ColumnInfo(name = "is_actionable") val isActionable: Boolean,
#ColumnInfo(name = "created_at") val createdAt: Instant,
#ColumnInfo(name = "is_read") val isRead: Boolean = false)
And this is my Dao Class
#Dao
internal interface NotificationDao {
#Query("SELECT * FROM NotificationEntity ORDER BY created_at ASC")
suspend fun getAllNotifications(): Flow<List<NotificationEntity>>
#Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun saveNotification(notifications: List<NotificationEntity>)
}
Can someone help what is the issue here?
When you declare Dao's function which returns Flow the function should not be suspendable. Please see docs.
Change your code to:
#Dao
internal interface NotificationDao {
#Query("SELECT * FROM NotificationEntity ORDER BY created_at ASC")
fun getAllNotifications(): Flow<List<NotificationEntity>>
#Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun saveNotification(notifications: List<NotificationEntity>)
}
And add type converter for Instant type which used in NotificationEntity if not yet added.

Type converter error on Android Room Database

java.lang.IllegalArgumentException: A required type converter (class SourceConverter) for ArticlesDao is missing in the database configuration.
I have a crash when compiling (runtime) my application because according to the error displayed, the converter is missing in the configuration of my database. how could I solve this? I need help please.
The source code below:
SourceConverter.kt
#ProvidedTypeConverter
internal class SourceConverter {
#TypeConverter
fun stringToSource(string: String?): SourceEntity = Gson().fromJson(string, SourceEntity::class.java)
#TypeConverter
fun sourceToString(list: SourceEntity?): String = Gson().toJson(list)
}
ArticleEntity.kt
#Entity(tableName = "article")
data class ArticleEntity(
#TypeConverters(SourceConverter::class)
#SerializedName("source")
var source: SourceEntity? = null,
#SerializedName("author")
var author: String? = null,
#SerializedName("title")
var title: String? = null,
#SerializedName("description")
var description: String? = null,
#SerializedName("url")
#NonNull #PrimaryKey var url: String,
#SerializedName("urlToImage")
var urlToImage: String? = null,
#SerializedName("publishedAt")
var publishedAt: String? = null,
#SerializedName("content")
var content: String? = null
)
ArticlesDao.kt
#Dao
interface ArticlesDao {
#Query("select * from article where url = :primaryId")
fun findByPrimaryId(primaryId: String?): ArticleEntity?
#Query("DELETE FROM article WHERE url = :primaryId")
fun deleteByPrimaryId(primaryId: String?): Int
#Query("SELECT * FROM article")
fun getAllArticles(): Flow<List<ArticleEntity>>
#Query("DELETE FROM article")
fun clear()
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(articleEntity: ArticleEntity?): Long
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg articleEntities: ArticleEntity?): LongArray?
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(articleEntityList: List<ArticleEntity?>?): LongArray?
#Update(onConflict = OnConflictStrategy.REPLACE)
fun update(articleEntity: ArticleEntity?): Int
#Update(onConflict = OnConflictStrategy.REPLACE)
fun update(vararg articleEntities: ArticleEntity?): Int
#Update(onConflict = OnConflictStrategy.REPLACE)
fun update(articleEntityList: List<ArticleEntity?>?): Int
#Delete
fun delete(articleEntity: ArticleEntity?): Int
}
AppDatabase.kt
#Database(entities = [ArticleEntity::class, SourceEntity::class], version = 1, exportSchema = false)
#TypeConverters(SourceConverter::class, ArticleConverter::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getArticlesDao(): ArticlesDao
abstract fun getSourcesDao(): SourcesDao
companion object {
#Synchronized
fun getInstance(context: Context): AppDatabase {
if (sInstance == null) {
sInstance = Room
.databaseBuilder(
context.applicationContext,
AppDatabase::class.java, "infotify.db"
)
.addTypeConverter(SourceConverter::class.java)
.build()
}
return sInstance as AppDatabase
}
}
}
There are three ways to add type converter to room database. But you should make sure you using one method only or it will get error:
add annotation at the type converter class header #ProvidedTypeConverter
Room.databaseBuilder.addTypeConverter(ConverterHelper::class)
add annotation at the RoomDatabase class header #TypeConverters(ConverterHelper::class)
Instead of
Room.databaseBuilder.addTypeConverter(ConverterHelper::class)
Use this:
Room.databaseBuilder.addTypeConverter(ConverterHelper())

Android Room #insert, how to insert a row with column filling, when creating a database

If you pass a single id value, then there will be no errors everything works. I pass When the remaining values are wordEn, wordRu, outputs an error:
No value passed for parameter 'wordEn'
No value passed for parameter 'wordRu'
how do I insert a row into a database with columns filled in?
See where <-!!!
#Dao
interface WordDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(id: Word, wordEn: Word, wordRu: Word)
}
#Entity(tableName = "word_table")
data class Word (
#PrimaryKey
var id: Int,
var wordEn: String,
var wordRu: List<String>
)
#Database(entities = [Word::class], version = 1, exportSchema = false)
abstract class AppRoomDatabase : RoomDatabase() {
....
....
val instance = Room.databaseBuilder(
context.applicationContext,
AppRoomDatabase::class.java,
"app_room_database"
)
.addCallback(WordDatabaseCallback(scope))
.build()
INSTANCE = instance
instance
}
}
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : RoomDatabase.Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
INSTANCE?.let { database ->
scope.launch(Dispatchers.IO) {
populateDatabase(database.wordDao())
}
}
}
}
suspend fun populateDatabase(wordDao: WordDao) {
//TEST Fill the database with random string
....
....
var randomInt: Int = randomInt()
var randomString: String = randomString()
var list: List<String> = list()
wordDao.insert(Word(randomInt , "$a _$randomString",list)) <- !!!
}
//TEST end
}
The insert statement is not correct
#Dao
interface WordDao {
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertWord(word: Word)
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertWords(words: List<Word>)
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertWords1(varargs words: Word)
}
Since Word is an entity
#Entity(tableName = "word_table")
data class Word (
#PrimaryKey
var id: Int,
var wordEn: String,
var wordRu: List<String>
)
Room 🔗 Coroutines

Count rows Android Room on Kotlin

learning Kotlin, proper app structure and stuff... Again... :)
So i have the following:
Dao
Repository
ViewModel
Dao Code
#Dao
interface ItemDao {
#Query("SELECT * from item_table ORDER BY Name ASC")
fun getSortedItems(): LiveData<List<Item>>
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(item: Item)
#Query("DELETE FROM item_table")
suspend fun deleteAll()
}
Repository
class ItemRepository (private val itemDao: ItemDao) {
val allItems: LiveData<List<Item>> = itemDao.getSortedItems()
suspend fun insert(item: Item) {
itemDao.insert(item)
}
}
ViewModel
class ItemViewModel(application: Application) : AndroidViewModel(application) {
private val repository: ItemRepository
val allItems: LiveData<List<Item>>
init {
val itemsDao = ItemDataBase.getDatabase(application, viewModelScope).itemDao()
repository = ItemRepository(itemsDao)
allItems = repository.allItems
}
fun insert(item: Item) = viewModelScope.launch {
repository.insert(item)
}
}
I need to get current amount of rows in a table and i was thinking of something like this:
add to Dao
#Query("SELECT COUNT(name) FROM item_table")
fun getAmount(): LiveData<Int>
and then in Repo
fun getAmount(): LiveData<Int>{
return itemDao.getAmount()
}
and the same in ViewModel
fun getAmount(): LiveData<Int> {
return repository.getAmount()
}
But again, should i also use an observer in Activity to get this value? Or, on the other hand, can i use just Int, while getting the table from DB as LiveData?

Type of the parameter must be a class annotated with #Entity

I'm working with Room persistance databases in android but i get this error
error: Type of the parameter must be a class annotated with #Entity or a collection/array of it.
test.android.orca.com.ws2db.Models.User... user);
Please help me
This is my DAO :
#Dao
abstract interface UserDao
{
#get:Query("SELECT * FROM user")
val getall: List<User>
#Query("SELECT * FROM user where name LIKE :name AND login LIKE :login")
fun findByName(name: String, login: String): User
#Query("SELECT COUNT(*) from user")
fun countUsers(): Int
#Insert
fun insertAll(users: List<User>)
#Delete
fun delete(vararg user: User)
}
This is my Entity
#Entity(tableName = "user")
class UserTable {
#PrimaryKey(autoGenerate = true)
var uid: Int = 0
#ColumnInfo(name = "name")
var name: String? = null
#ColumnInfo(name = "login")
var login: String? = null
#ColumnInfo(name = "id")
var id: Int = 0
#ColumnInfo(name="url")
var url: String? = null
#ColumnInfo(name="company")
var company:String?=null
}
Database
#Database(entities = [UserTable::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
private var INSTANCE: AppDatabase? = null
fun getAppDatabase(context: Context): AppDatabase? {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "user-database")
.allowMainThreadQueries()
.build()
}
return INSTANCE
}
fun destroyInstance() {
INSTANCE = null
}
}}
This is the error : https://i.stack.imgur.com/FnECR.jpg
You are mixing user and UserTable. User is valid for referencing your table, but your entity is UserTable
#Dao
abstract interface UserDao
{
#get:Query("SELECT * FROM user")
val getall: List<UserTable>
#Query("SELECT * FROM user where name LIKE :name AND login LIKE :login")
fun findByName(name: String, login: String): UserTable
#Query("SELECT COUNT(*) from user")
fun countUsers(): Int
#Insert
fun insertAll(users: List<UserTable>)
#Delete
fun delete(vararg user: UserTable)
}

Categories

Resources