Android 跨 DAO 的房间交易
Android Room transactions across DAOs
官方文档指出:
It is recommended to have multiple Dao classes in your codebase depending on the tables they touch.
并且可以用这样的 Transaction 注释来标记一个方法:
@Dao
public abstract class ProductDao {
@Insert
public abstract void insert(Product product);
@Delete
public abstract void delete(Product product);
@Transaction
public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
// Anything inside this method runs in a single transaction.
insert(newProduct);
delete(oldProduct);
}
}
但是如果一个事务跨越多个 DAO 怎么办?我应该将所有 DAO 合并为一个以支持交易,还是有更好的方法来做到这一点?
您可以使用RoomDatabase.runInTransaction(...)
类似于:
database.runInTransaction(new Runnable(){
@Override
public void run(){
Access all your daos here
}
});
事实 1:
在方法上使用@Transaction 会导致在Dao_Impl 生成的class 中覆盖该方法。此方法如下所示:
@Override
public void makeFieldInactive(final long fieldId) {
__db.beginTransaction();
try {
MyDao_Impl.super.makeFieldInactive(fieldId);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
事实 2:
运行InTransaction() 方法如下所示:
/**
* Executes the specified {@link Runnable} in a database transaction. The transaction will be
* marked as successful unless an exception is thrown in the {@link Runnable}.
* <p>
* Room will only perform at most one transaction at a time.
*
* @param body The piece of code to execute.
*/
@SuppressWarnings("deprecation")
public void runInTransaction(@NonNull Runnable body) {
beginTransaction();
try {
body.run();
setTransactionSuccessful();
} finally {
endTransaction();
}
}
结论:
他们都做同样的事情。
更多信息:
我已经做了一些测试,看起来使用其中一个(或两个,冗余)将成功地导致你的道方法在一次交易中 运行。
答案:
在访问同一个数据库的多个 Daos 中进行更改的方法上使用 @Transaction 是确保方法中发生的所有数据库操作发生在一个事务中的安全方法。
编辑:
在标记为 @Transactoin:
的一种方法中访问多个 Dao 的示例
@Transaction
public void addItem(ItemEntity item) {
item.setId(insert(item));
ItemReportDao itemReportDao = AppDatabase.getIntance().itemReportDao();
itemReportDao.addItemReport(item.getId());
}
官方文档指出:
It is recommended to have multiple Dao classes in your codebase depending on the tables they touch.
并且可以用这样的 Transaction 注释来标记一个方法:
@Dao
public abstract class ProductDao {
@Insert
public abstract void insert(Product product);
@Delete
public abstract void delete(Product product);
@Transaction
public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
// Anything inside this method runs in a single transaction.
insert(newProduct);
delete(oldProduct);
}
}
但是如果一个事务跨越多个 DAO 怎么办?我应该将所有 DAO 合并为一个以支持交易,还是有更好的方法来做到这一点?
您可以使用RoomDatabase.runInTransaction(...)
类似于:
database.runInTransaction(new Runnable(){
@Override
public void run(){
Access all your daos here
}
});
事实 1: 在方法上使用@Transaction 会导致在Dao_Impl 生成的class 中覆盖该方法。此方法如下所示:
@Override
public void makeFieldInactive(final long fieldId) {
__db.beginTransaction();
try {
MyDao_Impl.super.makeFieldInactive(fieldId);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
事实 2: 运行InTransaction() 方法如下所示:
/**
* Executes the specified {@link Runnable} in a database transaction. The transaction will be
* marked as successful unless an exception is thrown in the {@link Runnable}.
* <p>
* Room will only perform at most one transaction at a time.
*
* @param body The piece of code to execute.
*/
@SuppressWarnings("deprecation")
public void runInTransaction(@NonNull Runnable body) {
beginTransaction();
try {
body.run();
setTransactionSuccessful();
} finally {
endTransaction();
}
}
结论: 他们都做同样的事情。
更多信息: 我已经做了一些测试,看起来使用其中一个(或两个,冗余)将成功地导致你的道方法在一次交易中 运行。
答案: 在访问同一个数据库的多个 Daos 中进行更改的方法上使用 @Transaction 是确保方法中发生的所有数据库操作发生在一个事务中的安全方法。
编辑: 在标记为 @Transactoin:
的一种方法中访问多个 Dao 的示例@Transaction
public void addItem(ItemEntity item) {
item.setId(insert(item));
ItemReportDao itemReportDao = AppDatabase.getIntance().itemReportDao();
itemReportDao.addItemReport(item.getId());
}