Search code examples
androidandroid-sqliteandroid-room

Using Room, how to get the last inserted auto-generated ID , including when the table didn't get anything inserted into it?


Just a solution that someone wrote to me that I think could be useful:

Background

I just wanted to know if the table was ever been modified, so I thought that maybe by getting the last generated ID this could be a way to do it, and since I know this value should be saved somewhere, it should be possible to get it.

My idea :

Using Room, get the last inserted auto-generated ID (even if nothing was ever inserted) , without modifying the table or create any additional table.

The problem

I couldn't find a way to do it, so I requested about this here and asked here.

What I've found

There were some answers over StackOverflow for using "last_insert_rowid", but I failed to use it.

Here's a sample Room Database :

build.gradle

repositories {
    maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
}

...

apply plugin: 'kotlin-android-extensions'

...

final def room_version = '2.1.0'
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

...

DBProvider.kt

object DBProvider {
    const val DB_NAME = "room.db"
    lateinit var DB: MainDatabase

    fun init(context: Context) {
        //        Log.d("AppLog", "DBProvider init")
        DB = Room.databaseBuilder(context.applicationContext, MainDatabase::class.java, DB_NAME)
            .addCallback(object : RoomDatabase.Callback() {
            }).build()
    }

    @Database(
        entities = [FavoriteSpeedDialDTO::class],
        version = DB_VERSION,
        exportSchema = false
    )
    abstract class MainDatabase : RoomDatabase() {
        abstract fun favoriteSpeedDialDao(): FavoriteSpeedDialDao
        abstract fun dao(): SpecialDao
    }

}

FavoriteSpeedDialDao.kt

@Dao
abstract class FavoriteSpeedDialDao {
    @Query("SELECT * FROM favorite_speed_dial")
    abstract fun getFavoritesList(): MutableList<FavoriteSpeedDialDTO>

    @Insert
    abstract fun insert(item: FavoriteSpeedDialDTO): Long

    @Query("DELETE FROM favorite_speed_dial")
    abstract fun deleteAll(): Int

}

FavoriteSpeedDialDTO.kt

@Entity(tableName = "favorite_speed_dial")
@Parcelize
data class FavoriteSpeedDialDTO(@ColumnInfo(name = COL_ID) @PrimaryKey(autoGenerate = true) var id: Long,
                                @ColumnInfo(name = COL_ASSIGNED_PHONE_NUMBER) var phoneNumber: String) : Parcelable {
    companion object {
        const val COL_ID = BaseColumns._ID
        const val COL_ASSIGNED_PHONE_NUMBER = "assigned_phone_number"
    }
}

The question

Using Room, how to get the last generated ID of a table, even if nothing was added to it, ever, and also when it gets emptied?

Since I already found an answer, I posted it, but if you think there is another nice solution, feel free to post it.


Solution

  • And the answer:

    SpecialDao.kt

    @Suppress("AndroidUnresolvedRoomSqlReference")
    @Dao
    abstract class SpecialDao {
        @Query("SELECT seq FROM sqlite_sequence WHERE name = :tableName")
        abstract fun getSequenceNumber(tableName: String): Long?
    }
    

    Sample to show it works:

    MainActivity.kt

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            DBProvider.init(this)
            AsyncTask.execute {
                val dao = DBProvider.DB.dao()
                var sequenceNumber = dao.getSequenceNumber("favorite_speed_dial")
                Log.d("AppLog", "id:$sequenceNumber")
                val favoriteSpeedDialDao = DBProvider.DB.favoriteSpeedDialDao()
                var favoritesList = favoriteSpeedDialDao.getFavoritesList()
                Log.d("AppLog", "favoritesList:${favoritesList}")
                Log.d("AppLog", "deleting all and inserting a new item...")
                favoriteSpeedDialDao.deleteAll()
                favoriteSpeedDialDao.insert(FavoriteSpeedDialDTO(0L, "123"))
                favoritesList = favoriteSpeedDialDao.getFavoritesList()
                Log.d("AppLog", "favoritesList:${favoritesList}")
                sequenceNumber = dao.getSequenceNumber("favorite_speed_dial")
                Log.d("AppLog", "id:$sequenceNumber")
    
            }
        }
    
    
        companion object {
            fun toString(collection: Collection<*>?): String {
                if (collection == null)
                    return "null"
                val sb = StringBuilder("{")
                var isFirst = true
                for (`object` in collection) {
                    if (!isFirst)
                        sb.append(',')
                    else
                        isFirst = false
                    sb.append(`object`)
                }
                sb.append('}')
                return sb.toString()
            }
        }
    }