Room - 插入新值后执行删除
Posted
技术标签:
【中文标题】Room - 插入新值后执行删除【英文标题】:Room - Delete executes after I insert new values 【发布时间】:2019-04-20 00:45:33 【问题描述】:我正在研究 Rxjava2,我正在尝试将 Room Library 与 Rxjava2 集成。问题是:我有一个填充表,每次登录应用程序时,我都需要删除该表,然后在数据库中插入新内容。另外,删除和插入工作正常,但是当我在删除表内容后尝试插入新值时,delete 方法会删除所有新值..(部分代码在 kotlin 中,其他在 java 中) 我已经尝试过了:RxJava2 + Room: data is not being inserted in DB after clearAllTables() call,但没有成功..
道
@Dao
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(list:List<Something>)
@Query("DELETE FROM SomethingTable")
fun delete()
@Query("SELECT * FROM SomethingTable")
fun getAll(): Flowable<List<Something>>
我的类调用DAO(CallDao)
//insert
fun insertInDB(list: List<Something>)
Completable.fromAction
dbDAO!!.insert(list)
.observeOn(androidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe()
//delete
fun clean()
Completable.fromAction
dbDAO!!.delete()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe()
//search all
fun findAll(): Observable<List<Something>>?
return Observable.create subscriber ->
dbDAO!!.getAll()
.subscribeOn(Schedulers.io())
.subscribe it->
subscriber.onNext(it)
点击登录按钮时调用的方法
private void clearAndInsertInDB()
CallDao callDao= new CallDao(getActivity());
//delete all table values
callDao.clean();
Something sm = new Something("test1", "test2");
ArrayList<Something> list = new ArrayList<>();
list.add(sm);
list.add(sm);
//insert new values
callDao.insertInDB(list);
//get all new values in DB
callDao.findAll()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(res ->
//here gives me a IndexOutOfBoundsException
Log.d("logDebug", res.get(0).getCodeExemple());
);
也欢迎对我的代码进行任何更正 :),但主要问题是 delete 方法会删除所有新的插入值,它应该只删除旧值。
【问题讨论】:
不使用Query,而是使用@Delete注解删除单个项目并将Item对象作为参数传递 @deepakkumar,我想删除所有表格内容,而不是单个项目.. 抱歉,我理解错了,但是在插入或删除方法删除所有 tge 新值后执行 dele 的真正问题是什么?? 我的问题是:删除方法在我插入新值之前被调用,但是在我插入新值之后它正在执行。 可能是因为日程安排,但您可以通过等待操作完成来避免这种情况,方法是使用 Kotlin 协程中的 await 方法等待异步完成。 【参考方案1】:您正在进行两个异步调用:一个用于删除用户,另一个用于再次插入它们。但是,即使您先调用 callDao.clean();
方法,然后再调用 callDao.insertInDB(list);
,也不能保证 clean()
操作会在 insertInDB()
操作之前完成(因为这就是异步调用的工作方式)。
这是正在发生的事情:
相反,您应该链接您的异步调用,这样当您知道第一个调用已经完成时,第二个调用就会被调用。
如何使用RxJava
和Completable
实现这一目标?使用andThen
运算符,如in this answer 所述
您应该修改您的clean()
和insertInDB()
方法以返回Completables
,使用andThen
链接它们,然后订阅。
使用 RxJava 和 andThen() 的简单示例
FakeDatabase db = Room.databaseBuilder(this, FakeDatabase.class, "fake.db")
.fallbackToDestructiveMigration()
.build();
UserDao userDao = db.userDao();
User user1 = new User("Diego", "Garcia Lozano", "diegogarcialozano@fake.com");
User user2 = new User("Juan", "Perez", "juanperez@fake.com");
User user3 = new User("Pedro", "Lopez", "pedrolopez@fake.com");
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
Completable deleteAllCompletable = Completable.fromAction(userDao::deleteAll);
Completable insertUserCompletable = Completable.fromAction(() -> userDao.insertAll(users));
deleteAllCompletable
.andThen(Completable.fromAction(() -> System.out.println("Delete finished")))
.andThen(insertUserCompletable)
.andThen(Completable.fromAction(() -> System.out.println("Insert finished")))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();
执行后检查Logcat
,可以看到操作以正确的顺序执行:
2018-11-19 16:07:02.056 10029-10047/? I/System.out: Delete finished
2018-11-19 16:07:02.060 10029-10047/? I/System.out: Insert finished
之后,I checked the content of the database 使用工具 SQLite Browser 并看到插入工作正常。
在 DAO 中使用 @Transaction
您可以在完全不使用RxJava
的情况下为您的问题找到更好的解决方案。相反,您可以使用@Transaction 注释as explained in this post 在您的DAO 中定义Transaction
。它看起来像这样:
道
@Dao
public abstract class UserDao
@Transaction
public void deleteAndCreate(List<User> users)
deleteAll();
insertAll(users);
@Query("DELETE FROM User")
public abstract void deleteAll();
@Insert
public abstract void insertAll(List<User> users);
活动
Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();
检查表
就我个人而言,我会使用@Transaction
注释。
【讨论】:
感谢您的帮助!我没有检查为正确答案,因为我仍在尝试像你说的那样使用 Future 和 Completables,这有点困难:( 请检查我更新的答案。我会使用@Transaction 注释。干杯 最好的解决方案是特别适合我的情况,我有 4 个表向每个表插入数据并在发生冲突/错误时回滚。 您也可以使用 flatmap 来逐个调用每个 asnyn 并一次性返回成功与否以上是关于Room - 插入新值后执行删除的主要内容,如果未能解决你的问题,请参考以下文章
Python 如何在使用 Python 写入新值后保持 XML 注释存在?