[英]How to get id of the inserted entity when using ViewModel?
根问题:我想在[Entity B]的外键中设置[Entity A]的id,但是[Entity A]的id在插入数据库之前是不可用的(因为它是由DBMS自动生成的)。
使用体系结构组件(Room,ViewModel和LiveData),如何执行在数据库中保存多个相关实体的事务? 以下代码目前驻留在ViewModel中并且工作正常。 问题是我想将这个AsyncTask
放在存储库层中,就像其他简单的单操作查询一样,但它可以吗? 因为在这种情况下,存储库将负责管理关系和了解实体细节。
正如我上面所说,主要问题是我需要插入实体的id,所以我可以将它保存在另一个实体中。 如果此要求不存在,我将能够在存储库中的单独AsyncTask
中逐个持久化每个实体。
MainViewModel.java:
public void buy(Item item, Store store) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
long storeId = mRepository.insertStore(store);
Purchase purchase = new Purchase(storeId); // here uses id of the store
long purchaseId = mRepository.insertPurchase(purchase);
item.setPurchaseId(purchaseId); // here uses id of the purchase
mRepository.updateItem(item);
return null;
}
}.execute();
}
如果你把它保存在Repository层中,我认为你正在做的事情很好。 我不认为在ViewModel中保留它是一个好主意,因为它假设是Repository负责处理您的数据,在本例中是Item
和Store
对象。 我相信您的存储库应该负责管理这些数据及其关系。 要回答有关接收更新实体的ID的问题,您可以做的是让AsyncTask实现onPostExecute
方法并让doInBackground
方法返回实际值(如storeId
)而不是null
。 然后,您可以让onPostExecute
检索该值并将控制委托给某种类型的回调侦听器。
您可以使用Android Room在事务中执行多个数据库操作。 这样,您可以确保在其中一个操作失败(操作被回滚)的情况下不会更改您的数据库完整性。
以下是如何在Dao
类中定义具有Room的Transaction:
@Dao
public abstract class MyDao {
@Insert
public abstract long insertStore(Store store);
@Insert(onConflict = OnConflictStrategy.ROLLBACK)
public abstract long recordPurchase(Purchase purchase);
@Update
public abstract void updateItem(Item updatedItem);
@Transaction
public void buyItemFromStore(Item boughtItem, Store store) {
// Anything inside this method runs in a single transaction.
long storedId = insertStore(store);
Purchase purchase = new Purchase(storeId);
long purchaseId = recordPurchase(purchase);
item.setPurchaseId(purchaseId);
updateItem(item);
}
}
您可以参考文档以获取有关@Transaction
如何工作的说明。
然后在您的存储库类中,从AsyncTask
调用buyItemFromStore
:
public class MyRepository {
private MyDao dao;
public void buy(Item item, Store store) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doOnBackground(Void... voids) {
// Everything is saved in a transaction.
dao.buyItemFromStore(item, store);
return null;
}
}
}
}
请注意,只要存储的对象以某种方式相关(存储购买和项目似乎就是这种情况),这对于Repository
层来了解实体之间的关系是完全正确的。
如果您无法更改Dao
类,请考虑RoomDatabase.runInTransaction
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.