Room - Delete executes after I insert new values












0















I'm studying Rxjava2 and I'm trying to integrate the Room Library with Rxjava2. The problem is: I have a populated table and every time I login in the app, I need to delete this table and then insert a new content in database. Separately, the delete and insert works fine, but when I try to insert new values after I delete the table content, the delete method deletes all the new values.. (some parts of the code is in kotlin and others in java)

I already tried this: RxJava2 + Room: data is not being inserted in DB after clearAllTables() call, but no success..



DAO



@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>>


My class that calls the 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)
}
}
}


Method that is called when I click in login button



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());
});
}


Any corrections in my code is also welcome :) , but the main problem is that the delete method deletes all the new insert values and it should delete only the old values.










share|improve this question

























  • Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

    – deepak kumar
    Nov 16 '18 at 19:54











  • @deepakkumar, I want to delete all table content and not a single item..

    – barbs
    Nov 16 '18 at 19:55











  • Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

    – deepak kumar
    Nov 16 '18 at 20:01











  • my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

    – barbs
    Nov 16 '18 at 20:05











  • May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

    – deepak kumar
    Nov 16 '18 at 20:15
















0















I'm studying Rxjava2 and I'm trying to integrate the Room Library with Rxjava2. The problem is: I have a populated table and every time I login in the app, I need to delete this table and then insert a new content in database. Separately, the delete and insert works fine, but when I try to insert new values after I delete the table content, the delete method deletes all the new values.. (some parts of the code is in kotlin and others in java)

I already tried this: RxJava2 + Room: data is not being inserted in DB after clearAllTables() call, but no success..



DAO



@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>>


My class that calls the 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)
}
}
}


Method that is called when I click in login button



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());
});
}


Any corrections in my code is also welcome :) , but the main problem is that the delete method deletes all the new insert values and it should delete only the old values.










share|improve this question

























  • Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

    – deepak kumar
    Nov 16 '18 at 19:54











  • @deepakkumar, I want to delete all table content and not a single item..

    – barbs
    Nov 16 '18 at 19:55











  • Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

    – deepak kumar
    Nov 16 '18 at 20:01











  • my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

    – barbs
    Nov 16 '18 at 20:05











  • May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

    – deepak kumar
    Nov 16 '18 at 20:15














0












0








0








I'm studying Rxjava2 and I'm trying to integrate the Room Library with Rxjava2. The problem is: I have a populated table and every time I login in the app, I need to delete this table and then insert a new content in database. Separately, the delete and insert works fine, but when I try to insert new values after I delete the table content, the delete method deletes all the new values.. (some parts of the code is in kotlin and others in java)

I already tried this: RxJava2 + Room: data is not being inserted in DB after clearAllTables() call, but no success..



DAO



@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>>


My class that calls the 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)
}
}
}


Method that is called when I click in login button



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());
});
}


Any corrections in my code is also welcome :) , but the main problem is that the delete method deletes all the new insert values and it should delete only the old values.










share|improve this question
















I'm studying Rxjava2 and I'm trying to integrate the Room Library with Rxjava2. The problem is: I have a populated table and every time I login in the app, I need to delete this table and then insert a new content in database. Separately, the delete and insert works fine, but when I try to insert new values after I delete the table content, the delete method deletes all the new values.. (some parts of the code is in kotlin and others in java)

I already tried this: RxJava2 + Room: data is not being inserted in DB after clearAllTables() call, but no success..



DAO



@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>>


My class that calls the 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)
}
}
}


Method that is called when I click in login button



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());
});
}


Any corrections in my code is also welcome :) , but the main problem is that the delete method deletes all the new insert values and it should delete only the old values.







android kotlin rx-java2 android-room






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 20:07







barbs

















asked Nov 16 '18 at 19:49









barbsbarbs

525




525













  • Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

    – deepak kumar
    Nov 16 '18 at 19:54











  • @deepakkumar, I want to delete all table content and not a single item..

    – barbs
    Nov 16 '18 at 19:55











  • Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

    – deepak kumar
    Nov 16 '18 at 20:01











  • my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

    – barbs
    Nov 16 '18 at 20:05











  • May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

    – deepak kumar
    Nov 16 '18 at 20:15



















  • Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

    – deepak kumar
    Nov 16 '18 at 19:54











  • @deepakkumar, I want to delete all table content and not a single item..

    – barbs
    Nov 16 '18 at 19:55











  • Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

    – deepak kumar
    Nov 16 '18 at 20:01











  • my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

    – barbs
    Nov 16 '18 at 20:05











  • May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

    – deepak kumar
    Nov 16 '18 at 20:15

















Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

– deepak kumar
Nov 16 '18 at 19:54





Instead of using Query use @Delete annotation to delete a single item and pass the Item object as a parameter

– deepak kumar
Nov 16 '18 at 19:54













@deepakkumar, I want to delete all table content and not a single item..

– barbs
Nov 16 '18 at 19:55





@deepakkumar, I want to delete all table content and not a single item..

– barbs
Nov 16 '18 at 19:55













Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

– deepak kumar
Nov 16 '18 at 20:01





Sorry, I misunderstood but what's your real problem dele executing after insert or delete method deletes all tge new values??

– deepak kumar
Nov 16 '18 at 20:01













my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

– barbs
Nov 16 '18 at 20:05





my problem is: the delete method is being called before I insert the new values, but it is executing after I insert the new values.

– barbs
Nov 16 '18 at 20:05













May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

– deepak kumar
Nov 16 '18 at 20:15





May be it's because of schedules but you can avoid this by waiting for the operation to complete using await method like in the Kotlin Coroutines await for async to complete.

– deepak kumar
Nov 16 '18 at 20:15












2 Answers
2






active

oldest

votes


















3














You are making two asynchronous calls: one to delete the users and another to insert them. However, even though you call first the callDao.clean(); method and after that you call callDao.insertInDB(list); , it is not guaranteed that the clean operation will be executed before the insert operation (because that's how asynchronous calls work).



This is what is happening:



Async calls without waiting



Instead, you should chain your async calls , in such a way that the second one gets call as soon as you know that the first one has already finished.



Chained async calls



How to achieve that using RxJava? Using andThen operator as stated in this answer



You should modify your clean and insert methods to return the Completables, use andThen to chain them, and then subscribe.



Simple example using RxJava and 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();


Checking the Logcat after execution, you can see that the operations were executed in the proper order:



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


And then I checked the content of the database using the tool SQLite Browser and saw that the insert worked properly.



SqliteBrowser showing the proper data in the table



Using @Transaction in the DAO



You can also try to get a solution to your problem without using RxJava. Instead, you can define a Transaction in your DAO using the @Transaction operation, as explained in this post. It would look something like this:



Dao



@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);
}


Activity



Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();


Checking the table



Table using @Transcation



Personally, I would do it with the @Transaction annotation.






share|improve this answer


























  • Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

    – barbs
    Nov 19 '18 at 11:56











  • Please, check my updated answer. I would use the @Transaction annotation. Cheers

    – dglozano
    Nov 19 '18 at 19:42






  • 1





    Thanks a lot!! It's working now!! :)

    – barbs
    Nov 20 '18 at 17:50



















0














So do You have any values left after pressing the button?
I am not yet able to comment so I am asking here, sorry for that






share|improve this answer
























  • No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

    – barbs
    Nov 18 '18 at 1:33











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344456%2froom-delete-executes-after-i-insert-new-values%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














You are making two asynchronous calls: one to delete the users and another to insert them. However, even though you call first the callDao.clean(); method and after that you call callDao.insertInDB(list); , it is not guaranteed that the clean operation will be executed before the insert operation (because that's how asynchronous calls work).



This is what is happening:



Async calls without waiting



Instead, you should chain your async calls , in such a way that the second one gets call as soon as you know that the first one has already finished.



Chained async calls



How to achieve that using RxJava? Using andThen operator as stated in this answer



You should modify your clean and insert methods to return the Completables, use andThen to chain them, and then subscribe.



Simple example using RxJava and 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();


Checking the Logcat after execution, you can see that the operations were executed in the proper order:



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


And then I checked the content of the database using the tool SQLite Browser and saw that the insert worked properly.



SqliteBrowser showing the proper data in the table



Using @Transaction in the DAO



You can also try to get a solution to your problem without using RxJava. Instead, you can define a Transaction in your DAO using the @Transaction operation, as explained in this post. It would look something like this:



Dao



@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);
}


Activity



Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();


Checking the table



Table using @Transcation



Personally, I would do it with the @Transaction annotation.






share|improve this answer


























  • Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

    – barbs
    Nov 19 '18 at 11:56











  • Please, check my updated answer. I would use the @Transaction annotation. Cheers

    – dglozano
    Nov 19 '18 at 19:42






  • 1





    Thanks a lot!! It's working now!! :)

    – barbs
    Nov 20 '18 at 17:50
















3














You are making two asynchronous calls: one to delete the users and another to insert them. However, even though you call first the callDao.clean(); method and after that you call callDao.insertInDB(list); , it is not guaranteed that the clean operation will be executed before the insert operation (because that's how asynchronous calls work).



This is what is happening:



Async calls without waiting



Instead, you should chain your async calls , in such a way that the second one gets call as soon as you know that the first one has already finished.



Chained async calls



How to achieve that using RxJava? Using andThen operator as stated in this answer



You should modify your clean and insert methods to return the Completables, use andThen to chain them, and then subscribe.



Simple example using RxJava and 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();


Checking the Logcat after execution, you can see that the operations were executed in the proper order:



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


And then I checked the content of the database using the tool SQLite Browser and saw that the insert worked properly.



SqliteBrowser showing the proper data in the table



Using @Transaction in the DAO



You can also try to get a solution to your problem without using RxJava. Instead, you can define a Transaction in your DAO using the @Transaction operation, as explained in this post. It would look something like this:



Dao



@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);
}


Activity



Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();


Checking the table



Table using @Transcation



Personally, I would do it with the @Transaction annotation.






share|improve this answer


























  • Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

    – barbs
    Nov 19 '18 at 11:56











  • Please, check my updated answer. I would use the @Transaction annotation. Cheers

    – dglozano
    Nov 19 '18 at 19:42






  • 1





    Thanks a lot!! It's working now!! :)

    – barbs
    Nov 20 '18 at 17:50














3












3








3







You are making two asynchronous calls: one to delete the users and another to insert them. However, even though you call first the callDao.clean(); method and after that you call callDao.insertInDB(list); , it is not guaranteed that the clean operation will be executed before the insert operation (because that's how asynchronous calls work).



This is what is happening:



Async calls without waiting



Instead, you should chain your async calls , in such a way that the second one gets call as soon as you know that the first one has already finished.



Chained async calls



How to achieve that using RxJava? Using andThen operator as stated in this answer



You should modify your clean and insert methods to return the Completables, use andThen to chain them, and then subscribe.



Simple example using RxJava and 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();


Checking the Logcat after execution, you can see that the operations were executed in the proper order:



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


And then I checked the content of the database using the tool SQLite Browser and saw that the insert worked properly.



SqliteBrowser showing the proper data in the table



Using @Transaction in the DAO



You can also try to get a solution to your problem without using RxJava. Instead, you can define a Transaction in your DAO using the @Transaction operation, as explained in this post. It would look something like this:



Dao



@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);
}


Activity



Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();


Checking the table



Table using @Transcation



Personally, I would do it with the @Transaction annotation.






share|improve this answer















You are making two asynchronous calls: one to delete the users and another to insert them. However, even though you call first the callDao.clean(); method and after that you call callDao.insertInDB(list); , it is not guaranteed that the clean operation will be executed before the insert operation (because that's how asynchronous calls work).



This is what is happening:



Async calls without waiting



Instead, you should chain your async calls , in such a way that the second one gets call as soon as you know that the first one has already finished.



Chained async calls



How to achieve that using RxJava? Using andThen operator as stated in this answer



You should modify your clean and insert methods to return the Completables, use andThen to chain them, and then subscribe.



Simple example using RxJava and 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();


Checking the Logcat after execution, you can see that the operations were executed in the proper order:



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


And then I checked the content of the database using the tool SQLite Browser and saw that the insert worked properly.



SqliteBrowser showing the proper data in the table



Using @Transaction in the DAO



You can also try to get a solution to your problem without using RxJava. Instead, you can define a Transaction in your DAO using the @Transaction operation, as explained in this post. It would look something like this:



Dao



@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);
}


Activity



Completable.fromAction(() -> userDao.deleteAndCreate(users))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.single())
.subscribe();


Checking the table



Table using @Transcation



Personally, I would do it with the @Transaction annotation.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 19 '18 at 19:42

























answered Nov 16 '18 at 21:54









dglozanodglozano

923120




923120













  • Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

    – barbs
    Nov 19 '18 at 11:56











  • Please, check my updated answer. I would use the @Transaction annotation. Cheers

    – dglozano
    Nov 19 '18 at 19:42






  • 1





    Thanks a lot!! It's working now!! :)

    – barbs
    Nov 20 '18 at 17:50



















  • Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

    – barbs
    Nov 19 '18 at 11:56











  • Please, check my updated answer. I would use the @Transaction annotation. Cheers

    – dglozano
    Nov 19 '18 at 19:42






  • 1





    Thanks a lot!! It's working now!! :)

    – barbs
    Nov 20 '18 at 17:50

















Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

– barbs
Nov 19 '18 at 11:56





Thanks for your help! I didn't check as a correct answer, because I'm still trying to use Future and Completables like you said, and it's kind difficult :(

– barbs
Nov 19 '18 at 11:56













Please, check my updated answer. I would use the @Transaction annotation. Cheers

– dglozano
Nov 19 '18 at 19:42





Please, check my updated answer. I would use the @Transaction annotation. Cheers

– dglozano
Nov 19 '18 at 19:42




1




1





Thanks a lot!! It's working now!! :)

– barbs
Nov 20 '18 at 17:50





Thanks a lot!! It's working now!! :)

– barbs
Nov 20 '18 at 17:50













0














So do You have any values left after pressing the button?
I am not yet able to comment so I am asking here, sorry for that






share|improve this answer
























  • No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

    – barbs
    Nov 18 '18 at 1:33
















0














So do You have any values left after pressing the button?
I am not yet able to comment so I am asking here, sorry for that






share|improve this answer
























  • No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

    – barbs
    Nov 18 '18 at 1:33














0












0








0







So do You have any values left after pressing the button?
I am not yet able to comment so I am asking here, sorry for that






share|improve this answer













So do You have any values left after pressing the button?
I am not yet able to comment so I am asking here, sorry for that







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 17 '18 at 0:10









DimnessDimness

120110




120110













  • No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

    – barbs
    Nov 18 '18 at 1:33



















  • No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

    – barbs
    Nov 18 '18 at 1:33

















No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

– barbs
Nov 18 '18 at 1:33





No, I don't have any values. The delete method is being call after the insert method, and it should be the opposite.. it's like dglozano said, the problem is the async calls and I need them to be sync

– barbs
Nov 18 '18 at 1:33


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344456%2froom-delete-executes-after-i-insert-new-values%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?