Zaktualizuj określone pole elementu w pokoju Android


124

W moim nowym projekcie używam biblioteki trwałości pokoju systemu Android. Chcę zaktualizować niektóre pola tabeli. Próbowałem jak w moim Dao-

// Method 1:

@Dao
public interface TourDao {
    @Update
    int updateTour(Tour tour);
}

Ale kiedy próbuję zaktualizować za pomocą tej metody, aktualizuje ona każde pole jednostki, w której pasuje do wartości klucza podstawowego obiektu wycieczki. używałem@Query

// Method 2:

@Query("UPDATE Tour SET endAddress = :end_address WHERE id = :tid")
int updateTour(long tid, String end_address);

Działa, ale w moim przypadku będzie wiele zapytań, ponieważ mam wiele pól w mojej encji. Chcę wiedzieć, jak mogę zaktualizować niektóre pola (nie wszystkie), na przykład Method 1gdzie id = 1; (id to automatycznie generowany klucz podstawowy).

// Entity:

@Entity
public class Tour {
    @PrimaryKey(autoGenerate = true)
    public long id;
    private String startAddress;
    private String endAddress;
    //constructor, getter and setter
}

Jak zaktualizować listę w tabeli. Właściwie wstawiłem listę w tabeli według TypeConverter. Ale gdy nadchodzi z aktualizacją, nie działa. Proszę zasugerować, jeśli napotkałeś jakiś taki problem.
— Aman Gupta - ShOoTeR

@ AmanGupta-ShOoTeR Czy otrzymałeś jakieś rozwiązanie dla powyższego komentarza?
— skygeek

Moja biblioteka Kripton Persistence Library działa podobnie do tej biblioteki Room. Jeśli chcesz zobaczyć, jak rozwiązałem ten problem za pomocą Kripton, odwiedź abubusoft.com/wp/2019/10/02/ ...
— xcesco

@ AmanGupta-ShOoTeR Napotkałem tego rodzaju problemy podczas aktualizacji przy użyciu „@Query”. Następnie użyłem `` @Insert (onConflict = OnConflictStrategy.REPLACE) '', tworząc obiekt z tą samą wartością klucza podstawowego zamiast aktualizacji i zadziałało
— Rasel

Odpowiedzi:


68

Chcę wiedzieć, jak mogę zaktualizować niektóre pola (nie wszystkie), takie jak metoda 1, gdzie id = 1

Użyj @Query, tak jak w metodzie 2.

w moim przypadku jest zbyt długie zapytanie, ponieważ mam wiele pól w mojej encji

Następnie miej mniejsze jednostki. Lub nie aktualizuj pól indywidualnie, ale zamiast tego wykonuj bardziej zgrubne interakcje z bazą danych.

IOW, w samym Pokoju nie ma nic, co zrobi to, czego szukasz.


Czy można zaktualizować tabelę bez przekazywania parametrów? Mam na myśli zamianę wartości logicznej.
— Wisznu TB

1
@VishnuTB: Jeśli możesz utworzyć instrukcję SQL, która robi to, co chcesz, powinieneś móc jej używać @Query.
— CommonsWare

@CommonsWare to rozumiem. Chciałem pobrać zestaw wierszy z logiczną wartością true. ale Łuk pokoju nie pozwolił mi na przekazanie parametru prawda / fałsz. zamiast true =1,false=0 SELECT * FROM note_table WHERE isNoteArchived == 0
— Wisznu TB

4
W pokoju 2.2.0-alpha01 ( developer.android.com/jetpack/androidx/releases/ ) wprowadzono nowy parametr dla @Update, który pozwala ustawić obiekt docelowy. Powinno to umożliwić częściowe aktualizacje.
— Jonas

84

Według dokumentacji aktualizacji SQLite :

<!-- language: lang-java -->
@Query("UPDATE tableName SET 
    field1 = :value1,
    field2 = :value2, 
    ...
    //some more fields to update
    ...
    field_N= :value_N
    WHERE id = :id)

int updateTour(long id, 
               Type value1, 
               Type value2, 
               ... ,
               // some more values here
               ... ,
               Type value_N);

Przykład:

Jednostka:

@Entity(tableName = "orders")
public class Order {

@NonNull
@PrimaryKey
@ColumnInfo(name = "order_id")
private int id;

@ColumnInfo(name = "order_title")
private String title;

@ColumnInfo(name = "order_amount")
private Float amount;

@ColumnInfo(name = "order_price")
private Float price;

@ColumnInfo(name = "order_desc")
private String description;

// ... methods, getters, setters
}

Dao:

@Dao
public interface OrderDao {

@Query("SELECT * FROM orders")
List<Order> getOrderList();

@Query("SELECT * FROM orders")
LiveData<List<Order>> getOrderLiveList();

@Query("SELECT * FROM orders WHERE order_id =:orderId")
LiveData<Order> getLiveOrderById(int orderId);

/**
* Updating only price
* By order id
*/
@Query("UPDATE orders SET order_price=:price WHERE order_id = :id")
void update(Float price, int id);

/**
* Updating only amount and price
* By order id
*/
@Query("UPDATE orders SET order_amount = :amount, price = :price WHERE order_id =:id")
void update(Float amount, Float price, int id);

/**
* Updating only title and description
* By order id
*/
@Query("UPDATE orders SET order_desc = :description, order_title= :title WHERE order_id =:id")
void update(String description, String title, int id);

@Update
void update(Order order);

@Delete
void delete(Order order);

@Insert(onConflict = REPLACE)
void insert(Order order);
}

4
Czy możesz to wyjaśnić bardziej?
— Michael

1
Z podmiotem z pytania metoda DAO będzie wyglądać następująco: @Query ("UPDATE Tour SET endAddress =: end_address, startAdress =: start_address WHERE id =: tid) int updateTour (long tid, String end_address, String start_address);
— Jurij Pitulja

1
Miałem na myśli twoje rozwiązanie :) Lepiej mieć to tam, aby inni użytkownicy mogli to zobaczyć
— Michael

och, myślałem, że to oczywiste. Naprawiono teraz.
— Jurij Pitulja

14

Począwszy od pokoju 2.2.0 wydanego w październiku 2019 r., Można określić jednostkę docelową dla aktualizacji. Następnie, jeśli parametr aktualizacji jest inny, pomieszczenie zaktualizuje tylko kolumny części częściowej. Przykład pytania PO pokaże to nieco jaśniej.

@Update(entity = Tour::class)
fun update(obj: TourUpdate)

@Entity
public class TourUpdate {
    @ColumnInfo(name = "id")
    public long id;
    @ColumnInfo(name = "endAddress")
    private String endAddress;
}

Zauważ, że musisz utworzyć nową część częściową o nazwie TourUpdate, wraz z prawdziwym elementem Tour w pytaniu. Teraz, gdy wywołasz update z obiektem TourUpdate, zaktualizuje on endAddress i pozostawi tę samą wartość startAddress. Działa to idealnie dla mnie w moim przypadku zastosowania metody insertOrUpdate w moim DAO, która aktualizuje bazę danych nowymi zdalnymi wartościami z API, ale pozostawia dane lokalnej aplikacji w samej tabeli.


6

Możesz spróbować, ale wydajność może być trochę gorsza:

@Dao
public abstract class TourDao {

    @Query("SELECT * FROM Tour WHERE id == :id")
    public abstract Tour getTour(int id);

    @Update
    public abstract int updateTour(Tour tour);

    public void updateTour(int id, String end_address) {
        Tour tour = getTour(id);
        tour.end_address = end_address;
        updateTour(tour);
    }
}

2

Myślę, że nie musisz aktualizować tylko określonego pola. Po prostu zaktualizuj całe dane.

@Update zapytanie

W zasadzie jest to zadane zapytanie. Nie ma potrzeby wykonywania nowego zapytania.

@Dao
interface MemoDao {

    @Insert
    suspend fun insert(memo: Memo)

    @Delete
    suspend fun delete(memo: Memo)

    @Update
    suspend fun update(memo: Memo)
}

Memo.class

@Entity
data class Memo (
    @PrimaryKey(autoGenerate = true) val id: Int,
    @ColumnInfo(name = "title") val title: String?,
    @ColumnInfo(name = "content") val content: String?,
    @ColumnInfo(name = "photo") val photo: List<ByteArray>?
)

Jedyne, co musisz wiedzieć, to „id”. Na przykład, jeśli chcesz zaktualizować tylko „tytuł”, możesz ponownie użyć „treści” i „zdjęcia” z już wstawionych danych. W prawdziwym kodzie użyj w ten sposób

val memo = Memo(id, title, content, byteArrayList)
memoViewModel.update(memo)

-3

Jeśli chcesz zaktualizować informacje o użytkowniku dla określonego identyfikatora użytkownika „x”,

  1. musisz utworzyć klasę dbManager , która zainicjuje bazę danych w swoim konstruktorze i będzie działać jako pośrednik między Twoim viewModel i DAO, a także.
  2. ViewModel będzie zainicjować instancję dbManager dostępu do bazy danych. Kod powinien wyglądać następująco:

       @Entity
        class User{
        @PrimaryKey
        String userId;
        String username;
        }
    
        Interface UserDao{
        //forUpdate
        @Update
        void updateUser(User user)
        }
    
        Class DbManager{
        //AppDatabase gets the static object o roomDatabase.
        AppDatabase appDatabase;
        UserDao userDao;
        public DbManager(Application application ){
        appDatabase = AppDatabase.getInstance(application);
    
        //getUserDao is and abstract method of type UserDao declared in AppDatabase //class
        userDao = appDatabase.getUserDao();
        } 
    
        public void updateUser(User user, boolean isUpdate){
        new InsertUpdateUserAsyncTask(userDao,isUpdate).execute(user);
        }
    
    
    
        public static class InsertUpdateUserAsyncTask extends AsyncTask<User, Void, Void> {
    
    
         private UserDao userDAO;
         private boolean isInsert;
    
         public InsertUpdateBrandAsyncTask(BrandDAO userDAO, boolean isInsert) {
           this. userDAO = userDAO;
           this.isInsert = isInsert;
         }
    
         @Override
         protected Void doInBackground(User... users) {
           if (isInsert)
        userDAO.insertBrand(brandEntities[0]);
           else
        //for update
        userDAO.updateBrand(users[0]);
        //try {
        //  Thread.sleep(1000);
        //} catch (InterruptedException e) {
        //  e.printStackTrace();
        //}
           return null;
         }
          }
        }
    
         Class UserViewModel{
         DbManager dbManager;
         public UserViewModel(Application application){
         dbmanager = new DbMnager(application);
         }
    
         public void updateUser(User user, boolean isUpdate){
         dbmanager.updateUser(user,isUpdate);
         }
    
         }
    
    
    
    
    Now in your activity or fragment initialise your UserViewModel like this:
    
    UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
    

    Następnie zaktualizuj swój element użytkownika w ten sposób, załóżmy, że twój identyfikator użytkownika to 1122, a nazwa użytkownika to „xyz”, który należy zmienić na „zyx”.

    Uzyskaj obiekt userItem o identyfikatorze 1122 User

User user = new user();
 if(user.getUserId() == 1122){
   user.setuserName("zyx");
   userViewModel.updateUser(user);
 }

To jest surowy kod, mam nadzieję, że ci pomoże.

Miłego kodowania


10
Naprawdę wykonujesz działania związane z bazami danych w modelu widoku ??? god no plz no ...: '(po prostu zobacz nazwę modelu, która powinna uderzyć cię w twarz
— mcfly

@mcfly, dlaczego wykonywanie operacji na bazie danych w modelu widoku jest uważane za złe?
— Daniel

zasada odpowiedzialności pojedynczej jest złamana tak
— mcfly
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.