2017-06-23 50 views
8

Dzięki nowej bazie danych Pokój w Androidzie, Mam wymóg gdzie istnieją dwie operacje sekwencyjne, które muszą być wykonane:transakcje bazodanowe Android Pokoju

removeRows(ids); 
insertRows(ids); 

Jeśli uruchomię to widzę (na rozpatrzenie db), że brakuje niektórych wierszy - zakładam, że są one usuwane po wstawieniu. mianowicie. pierwsza operacja działa równolegle do drugiej.

Jeśli używam blok transakcji, takich jak ten, to wszystko jest w porządku - pierwsza operacja wydaje się zakończyć przed wykonaniem drugiego:

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

insertRows(ids); 

To też dobrze, jeśli daję spać w między zamiast :

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

insertRows(ids); 

nie wydaje się być dużo dokumentacji do pokoju, i zastanawiałem się, czy powinienem użyć bloku transakcji jak wyżej, kiedy mam operacji sekwencyjnych do zrobienia, czy jest jakiś lepszy sposób to.

EDIT Po @CommonsWare wskazał, @Query są asynchroniczne, a @Insert i @Delete są synchroniczne. W związku z tym, w jaki sposób uzyskać kwerendę, która usuwa wiersze być asynchroniczny:

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

Według wyjściu kompilacji dostaję Deletion methods must either return void or return int (the number of deleted rows), jeśli staram się zawinąć typ zwracany w Flowable.

+1

Jakie dokładnie są implementacje 'removeRows()' i 'insertRows()'? Jeśli są to zwykłe metody "@ Delete" i "@ Insert" DAO, to powinny być serializowane naturalnie, ponieważ te metody są wykonywane synchronicznie. Jedynym miejscem, w którym Room robi asynchroniczne rzeczy, jest '@ Query' z reaktywną wartością zwracaną (' LiveData', 'Flowable', itp.). – CommonsWare

+0

@CommonsWare, tak, podczas gdy 'insertRows()' są proste '@ Insert',' removeRows() 'mają wywołania' @ Query'. Myślę, że to wyjaśnia. Tak więc myślę, że odpowiedź na moje pytanie brzmi: zasubskrybuj odpowiedzi reaktywne Zapytań. – rajath

+0

@CommonsWare, dzięki za pomoc. Zmodyfikowałem to pytanie, uzupełniając go na podstawie Twojego komentarza. Jak mogę napisać '@ Query', który robi' DELETE', aby móc go obserwować do końca? – rajath

Odpowiedz

5

Jak zauważyli @CommonsWare, @Query są asynchroniczne, podczas gdy @Insert, @Delete, @Update są synchroniczne.

Jeśli chcesz wykonać wiele zapytań w pojedynczej transakcji, Room udostępnia również metodę, o której mowa poniżej.

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

Mam nadzieję, że rozwiąże to Twój problem.

5

jak wskazano na dokumentacji Transaction, można wykonać następujące czynności:

@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

co jeśli używam interfejsów? –

+2

@johnny_crq Używałem interfejsów i nie było trudno przejść do klas abstrakcyjnych. alternatywnie możesz wypróbować tę paskudną sztuczkę w interfejsie '@Transaction @Query (" USUŃ Z PRODUKTÓW, INSERT INTO WARTOŚCI PRODUKTU (x, y, z) ") nad metodą. – guness