Androidでcreated_at
ツールを使用してupdated_at
列とRoom Persistence ORM
列を実装すると、テーブルの行を作成または更新するときにタイムスタンプを自動的に更新できますか?
多くのサイトを調査しましたが、middleware
、callbacks
、Query
、またはInsert
、... Update
sのメソッドを使用した場合、Delete
またはDAO
のような結果を処理できる結果はまだ見つかりません。
@selvinが言ったように、RoomDatabase.Callback
インターフェイスは、データベースが最初に作成されたときにのみ呼び出されます。そのため、そのインターフェースを使用する方法は正しくありません。だから、以下の方法は私にとってトリックです、これがあなたを助けることを願っています:
BaseModel
を作成する必要がありますこのモデルにより、データベース内のすべてのモデルが常に利用可能な列creation_date
および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
を作成しますBaseDAO
の内部では、DAOWrapper
という名前のラッパークラスも作成します。このクラスは、モデルのデータをDAOに送る前に「ミドルウェア」などのデータを処理するために使用するすべての便利なメソッドを格納します。
つまり、BaseDAO
内にメソッドを作成しないのはなぜですか?->それはできません!その方法を使用すると、競合しますAndroid=アーキテクチャ、およびコンパイラからのエラーも発生します(DAOオブジェクトで宣言されたすべてのメソッドには、注釈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)
以下は、上記のコードで使用したRoomDatabaseの例とモデルの例です。
/** 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()
}
}
}
}
上記のJavaの例。
すべてのRoomエンティティの基本エンティティこれは、id、created_atおよびupdated_at列を含むテーブルにマップされます。
public abstract class BaseEntity implements Serializable {
@PrimaryKey(autoGenerate = true)
private long id;
@ColumnInfo(name = "created_at", defaultValue = "CURRENT_TIMESTAMP")
@TypeConverters(DateConverter.class)
private Date createdAt;
@ColumnInfo(name = "updated_at", defaultValue = "CURRENT_TIMESTAMP")
@TypeConverters(DateConverter.class)
private Date updatedAt;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
}
部屋の日付TypeConverterこれは、Java日付をsqliteデータベースに保存できる数値に変換します。
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
if (timestamp == null) {
return null;
}
return new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
if (date == null) {
return null;
}
return date.getTime();
}
}
抽象BaseDaoこのDaoは、すべての基本的なInsert、Update、およびDeleteメソッドを実装します。
@Dao
public abstract class AbstractBaseEntityDao<T extends BaseEntity> {
@Insert
public abstract long actualInsert(T t);
public long insert(T t) {
t.setCreatedAt(new Date());
t.setUpdatedAt(new Date());
return actualInsert(t);
}
@Insert
public abstract List<Long> actualInsertAll(List<T> ts);
public List<Long> insertAll(List<T> ts) {
if (ts != null) {
for (T t : ts) {
t.setCreatedAt(new Date());
t.setUpdatedAt(new Date());
}
}
return actualInsertAll(ts);
}
@Update
public abstract void actualUpdate(T t);
public void update(T t) {
t.setUpdatedAt(new Date());
actualUpdate(t);
}
@Update
public abstract void actualUpdateAll(List<T> ts);
public void updateAll(List<T> ts) {
if (ts != null) {
for (T t : ts) {
t.setUpdatedAt(new Date());
}
}
actualUpdateAll(ts);
}
@Delete
public abstract void delete(T t);
@Delete
public abstract void deleteAll(List<T> ts);
}
ser and UserDaoこれは、ユーザーの具体的なエンティティとDaoの例です(通常の使用例)。
@Entity(tableName = "users")
public class User extends BaseEntity {
@ColumnInfo(name = "name")
private String name;
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Dao
public abstract class UserDao extends AbstractBaseEntityDao<User> {
@Query("select * from users")
public abstract List<User> getAllUsers();
}
ユーザーの挿入方法これは、created_atおよびupdated_atタイムスタンプを設定するAbstractBaseEntityDaoを使用します。
注:UIスレッドではこれを行わないでください。
YourDatabase database = YourDatabase.getInstance(getApplicationContext());
UserDao userDao = database.userDao();
long userId = userDao.insert(userToAdd);
userToAdd.setId(userId);
ユーザーの更新方法
YourDatabase database = YourDatabase.getInstance(getApplicationContext());
UserDao userDao = database.userDao();
userDao.update(userToEdit);