根本问题:我想在[实体B]的外键中设置[实体A]的ID,但是[实体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();
}
答案 0 :(得分:1)
如果将其保存在“存储库”层中,我认为您正在做的事很好。我认为将其保留在ViewModel中并不是一个好主意,因为这是存储库负责处理数据的责任,在这种情况下,Item
和Store
对象是您的责任。我相信您的存储库应该负责此数据及其关系的管理。要回答有关接收更新后的实体的ID的问题,您可以做的是让AsyncTask实现onPostExecute
方法,并使doInBackground
方法返回实际值(例如storeId
),而不是null
。然后,您可以让onPostExecute
检索该值并将控制委托给某种回调侦听器。
答案 1 :(得分:0)
您可以使用Android Room在一个事务中执行多个数据库操作。 这样,可以确保在其中一项操作失败(操作已回滚)的情况下,不会更改数据库完整性。
在这里,您可以在Dao
类中定义带有房间的交易:
@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
的工作原理,您可以参考documentation。
然后在您的存储库类中,从buyItemFromStore
中调用AsyncTask
:
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;
}
}
}
}
请注意,只要存储的对象以某种方式关联(对于Store Purchase和Item来说似乎如此),Repository
层就可以很好地了解实体之间的关系。
如果您无法更改自己的Dao
类,请考虑使用RoomDatabase.runInTransaction
。