2017-06-23 105 views
8

随着Android的新房间数据库,我在那里有两个连续的操作需要作出要求:安卓室数据库事务

removeRows(ids); 
insertRows(ids); 

如果我跑这一点,我看到(考查分贝)有一些行丢失 - 我假设它们在插入后被删除。即第一个操作与第二个操作并行。

如果我使用一个事务块,像这样的,那么这一切都很好 - 第一操作似乎在做第二个前完成:

roomDb.beginTransaction(); 
removeRows(ids); 
roomDb.endTransaction(); 

insertRows(ids); 

它也很好,如果我给睡在中间,而不是:

removeRows(ids); 
Thread.sleep(500); 

insertRows(ids); 

似乎没有成为房多文档,并且在想,如果当时我有顺序操作做我应该使用事务块像上面,或者是有这样做的没有更好的办法它。

EDIT:@CommonsWare指出后,@Query是异步的,而@Insert@Delete是同步的。鉴于此,我将如何得到它删除行是异步的查询:

@Query("DELETE from table WHERE id IN(:ids)") 
int removeRows(List<Long> ids); 

据生成输出我得到Deletion methods must either return void or return int (the number of deleted rows),如果我尝试包裹返回类型的Flowable

+1

究竟是什么'removeRows()'和'insertRows()'的实现?如果它们是普通的'@ Delete'和'@ Insert' DAO方法,那么它们应该被自然地序列化,因为这些方法是同步执行的。 Room不同步的唯一地方是'@ Query',它具有反应返回值('LiveData','Flowable'等)。 – CommonsWare

+0

@CommonsWare,是的,虽然'insertRows()'很简单'@ Insert','removeRows()'有'@ Query'调用。我想这可以解释它。所以,我想我的问题的答案是订阅查询的被动反应。 – rajath

+0

@CommonsWare,谢谢你的帮助。我已根据您的评论进行了后续编辑。我怎样才能写一个'@ Query'做一个'DELETE',这样我可以观察它直到完成? – rajath

回答

5

正如@CommonsWare所指出的,@Query是异步的,而@Insert,@Delete,@Update是同步的。

如果您想要在单个事务中执行多个查询,Room还为此提供了一个方法,如下所述。

roomDB.runInTransaction(new Runnable() { 
     @Override 
     public void run() { 
      removeRows(ids); 
      insertRows(ids); 
     } 
    }); 

我希望这能解决您的问题。

5

如指出,在文档Transaction,你可以做到以下几点:

@Dao 
public abstract class ProductDao { 
    @Insert 
    public abstract void insert(Product product); 

    @Delete 
    public abstract void delete(Product product); 

    @Transaction 
    public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) { 
     // Anything inside this method runs in a single transaction. 
     insert(newProduct); 
     delete(oldProduct); 
    } 
} 
+0

如果我使用接口怎么办? –

+2

@johnny_crq我正在使用接口,并不难切换到抽象类。或者,您可以在接口'@Transaction @Query(“DELETE FROM products; INSERT INTO products VALUES(x,y,z)”)''方法上尝试这种丑陋的技巧。 – guness