With the new Room Database in Android, I have a requirement where there are two sequential operations that needs to be made:
removeRows(ids);
insertRows(ids);
If I run this, I see (on examining the db) that there are some rows missing - I assume they are being deleted after inserting. viz. the first operation is running in parallel to the second.
If I use a transaction block, such as this, then it's all fine - the first operation seems to complete before doing the second:
roomDb.beginTransaction();
removeRows(ids);
roomDb.endTransaction();
insertRows(ids);
It's also fine if I give a sleep in-between instead:
removeRows(ids);
Thread.sleep(500);
insertRows(ids);
There doesn't seem to be much documentation for Room, and was wondering if I should use the transaction block like the above when I have sequential operations to be done, or is there any better way of doing it.
EDIT: After @CommonsWare pointed out, @Query
are asynchronous, while @Insert
and @Delete
are synchronous. In view of this, how would I get a query which deletes rows to be async:
@Query("DELETE from table WHERE id IN(:ids)")
int removeRows(List<Long> ids);
According to the build output I get Deletion methods must either return void or return int (the number of deleted rows)
, if I try to wrap the return type in a Flowable
.
removeRows()
andinsertRows()
? If they are plain@Delete
and@Insert
DAO methods, then they should be serialized naturally, as those methods are executed synchronously. The only place where Room does asynchronous stuff is on@Query
with a reactive return value (LiveData
,Flowable
, etc.). – PhaidrainsertRows()
are simple@Insert
, theremoveRows()
have@Query
calls. I guess that explains it. So, the I guess the answer to my question is to subscribe to the reactive response of the Queries. – Swampland@Query
that does aDELETE
so that it I can observe it until completion? – Swampland@Query
that returns anint
is supposed to be synchronous. As I wrote, the only place where Room does asynchronous stuff is on@Query
with a reactive return value (LiveData
,Flowable
, etc.). It could be that this is a bug in Room somewhere. Is there a particular reason you are using@Query
rather than@Delete
?@Delete
already offersIN
support for a list of IDs. – PhaidraremoveRows
is only one of two deletion operations that I do. The other one has a more involved query which, if you think it'll help, I can add to the question. Can you also tell me or point me to where@Delete
offersIN
support for a list of IDs? – Swampland@Insert
,@Update
, and@Delete
each accept a single ID, a collection of IDs, or a varargs of IDs. developer.android.com/topic/libraries/architecture/… – Phaidra@Query
all the entities and pass them to@Delete
, but that'll be a hit on the performance. Maybe that feature request is a good idea :-) – Swampland@Query
returningint
should be synchronous, as that is not a reactive return value. Try putting a breakpoint where you are callingremoveRows()
, then step through the generated code and see if the query is being executed synchronously or asynchronously. You could do the same with yourinsertRows()
. If one or the other is asynchronous (which they shouldn't be), then that would help explain your symptoms. – Phaidra@Query
call embedded in my code, based on which I had to do some computation and delete some of the rows. This former call was async, and was causing issues. The@Delete
and@Insert
calls themselves ARE synchronous. Thanks a bunch for you help. – Swampland@Delete
(and also@Update
) searches rows based on primary key. So if you set your ID as@PrimaryKey
, then you create a dummy object with desired ID as key and then pass it to delete function. – Weichsel