web-dev-qa-db-ja.com

androidでルーム永続性ORMツールを使用してcreated_atおよびupdated_at列を実装する方法

Androidでcreated_atツールを使用してupdated_at列とRoom Persistence ORM列を実装すると、テーブルの行を作成または更新するときにタイムスタンプを自動的に更新できますか?

10

多くのサイトを調査しましたが、middlewarecallbacksQuery、またはInsert、... Updatesのメソッドを使用した場合、DeleteまたはDAOのような結果を処理できる結果はまだ見つかりません。

@selvinが言ったように、RoomDatabase.Callbackインターフェイスは、データベースが最初に作成されたときにのみ呼び出されます。そのため、そのインターフェースを使用する方法は正しくありません。だから、以下の方法は私にとってトリックです、これがあなたを助けることを願っています:

1. 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())

}

2. BaseDAOを作成します

BaseDAOの内部では、DAOWrapperという名前のラッパークラスも作成します。このクラスは、モデルのデータをDAOに送る前に「ミドルウェア」などのデータを処理するために使用するすべての便利なメソッドを格納します。

つまり、BaseDAO内にメソッドを作成しないのはなぜですか?->それはできません!その方法を使用すると、競合しますAndroid=アーキテクチャ、およびコンパイラからのエラーも発生します(DAOオブジェクトで宣言されたすべてのメソッドには、注釈UpdateQuery、...が必要です)。

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)
            }

        }

    }

}

3. 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()
            }
        }
    }

}
7
dphans

上記の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);
1
Dagmar