How can I implement created_at
and updated_at
columns using Room Persistence ORM
tools in Android, that can update the timestamp automatically when creating or updating a row in a table?
I've research many sites, but still not found any results can handle middleware
or something like callbacks
when we Query
, Insert
, Update
, or Delete
,... methods from DAO
s.
As @selvin said, RoomDatabase.Callback
interface only call when database created in first time. So, use that interface is incorrect way.
So, may be the way below is a trick for me, hope this will help you:
BaseModel
This model to sure that all models in database always available columns creation_date
and modification_date
.
abstract class BaseModel: Serializable {
@PrimaryKey(autoGenerate = true)
@Expose
var id: Long = 0
@ColumnInfo(name = "description")
@SerializedName(value = "description")
var description: String? = null
@ColumnInfo(name = "creation_date")
@SerializedName(value = "creation_date")
var creationDate: Date = Date(System.currentTimeMillis())
@ColumnInfo(name = "modification_date")
@SerializedName(value = "modification_date")
var modificationDate: Date = Date(System.currentTimeMillis())
}
BaseDAO
Inside BaseDAO
, I also create a wrapper class named DAOWrapper
, this class will store all helpful methods that we will use to process data like "middleware" before interact model's data to DAO.
So, why we don't create methods inside BaseDAO
?
-> We cannot do that! use that way will conflict android architecture and also we will have error from compiler (all methods declared in DAO object requires annotation Update
, Query
,...).
interface BaseDAO<T> where T: BaseModel {
fun getAll(): List<T>
@Insert(onConflict = OnConflictStrategy.ABORT)
fun insert(modelData: T)
@Update(onConflict = OnConflictStrategy.ABORT)
fun update(modelData: T)
companion object {
open class DAOWrapper<P, T>(private val daoInstance: T) where T: BaseDAO<P>, P: BaseModel {
fun insertWithTimestapData(modelData: P) {
modelData.modificationDate = Date(System.currentTimeMillis())
[email protected](modelData)
}
}
}
}
DAOWrapper
val appDatabase = // Do something to get RoomDatabase instance...
val exampleDao = appDatabase.exampleDAO()
val exampleDaoWrapper = BaseDAO.Companion.DAOWrapper(exampleDao)
val exampleModel = ExampleModel(name = "Example Name")
exampleDaoWrapper.insertWithTimestapData(exampleModel)
Below is example instance of RoomDatabase and example model I used in code above:
/** ExampleModel.kt */
@Entity(
tableName = "examples",
indices = [Index(value = arrayOf("name"), unique = true)]
)
class ExampleModel(): BaseModel() {
@ColumnInfo(name = "name")
@SerializedName(value = "name")
var name: String = String()
@Ignore
constructor(name: String): this() {
[email protected] = name
}
}
/** ExampleDAO.kt */
@Dao
interface ExampleDAO: BaseDAO<ExampleModel> {
@Query("SELECT * FROM `examples`")
override fun getAll(): List<ExampleModel>
}
/** AppDatabase.kt **/
@Database(entities = [ExampleModel::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
abstract fun exampleDAO(): ExampleDAO
companion object {
private var databaseInstance: AppDatabase? = null
public const val DatabaseName: String = "app_database"
fun getDatabase(context: Context): AppDatabase {
[email protected](context)
return [email protected]!!
}
fun destroyAndCreateNewInstanceIfNeeded(context: Context) {
synchronized(AppDatabase::class) {
[email protected]?.close()
[email protected] = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
[email protected]
).build()
}
}
}
}