繁体   English   中英

使用ViewModel时如何获取插入实体的id?

[英]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负责处理您的数据,在本例中是ItemStore对象。 我相信您的存储库应该负责管理这些数据及其关系。 要回答有关接收更新实体的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM