2017-06-23 103 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