Android Odasında bir varlığın belirli bir alanını güncelleyin


124

Yeni projem için android oda kalıcılık kitaplığı kullanıyorum. Bazı tablo alanlarını güncellemek istiyorum. Benim gibi denedim Dao-

// Method 1:

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

Ancak bu yöntemi kullanarak güncellemeye çalıştığımda, tur nesnesinin birincil anahtar değeriyle eşleştiği varlığın her alanını güncelliyor. Kullandım@Query

// Method 2:

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

Çalışıyor ama benim durumumda birçok sorgu olacak çünkü varlığımda birçok alan var. Method 1İd = 1 olduğu gibi bazı alanları (tümünü değil) nasıl güncelleyebilirim bilmek istiyorum ; (id, otomatik oluşturulan birincil anahtardır).

// Entity:

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

Tablodaki bir liste nasıl güncellenir? Aslında listeyi TypeConverter'a göre Tabloya ekledim. Ancak güncelleme ile gelirken çalışmıyor. Lütfen böyle bir sorunla karşılaştıysanız önerin.
Aman Gupta - ShOoTeR

@ AmanGupta-ShOoTeR Yukarıdaki yorum için herhangi bir çözüm buldunuz mu?
skygeek

Kitaplığım Kripton Kalıcı Kitaplığı, bu Oda kitaplığına oldukça benzer şekilde çalışıyor. Kripton kullanarak bu sorunu nasıl çözdüğüme
xcesco

@ AmanGupta-ShOoTeR '@Query' kullanarak güncellemede bu tür sorunlarla karşılaştım. Daha sonra güncelleme yerine aynı birincil anahtar değerine sahip bir nesne oluşturarak '@Insert (onConflict = OnConflictStrategy.REPLACE)' kullandım ve işe yaradı
Rasel

Yanıtlar:


68

İd = 1 olduğunda yöntem 1 gibi bazı alanları (tümünü değil) nasıl güncelleyebilirim bilmek istiyorum

@QueryYöntem 2'de yaptığınız gibi kullanın .

benim durumumda çok uzun bir sorgu çünkü varlığımda birçok alan var

Daha sonra daha küçük varlıklara sahip olun. Ya da alanları tek tek güncellemeyin, bunun yerine veritabanıyla daha kaba taneli etkileşimlere sahip olun.

IOW, Odanın içinde aradığınızı yapacak hiçbir şey yok.


Herhangi bir parametre geçmeden tabloyu güncellemek mümkün müdür? Bir boole değerini değiştirmek demek istiyorum.
Vishnu TB

1
@VishnuTB: İstediğinizi yapan bir SQL ifadesi oluşturabiliyorsanız, onu kullanabilmelisiniz @Query.
CommonsWare

@CommonsWare anladı. Boole gerçek değerine sahip bir dizi satırı getirmek istedim. ancak Oda kemeri parametre olarak true / false geçmeme izin vermedi. bunun yerine true =1,false=0 SELECT * FROM note_table WHERE isNoteArchived == 0
Vishnu TB

4
Oda 2.2.0-alpha01 ( developer.android.com/jetpack/androidx/releases/… ) @Update için hedef varlığı ayarlamanıza izin veren yeni bir parametre sundu. Bu, kısmi güncellemeleri mümkün kılmalıdır.
Jonas

85

Göre SQLite Güncelleme Dokümanlar :

<!-- 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);

Misal:

Varlık:

@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
Bunu biraz daha açıklayabilir misin?
Michael

1
Sorudan gelen varlıkla DAO yöntemi şöyle görünecektir: @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
Çözümünüzü kastetmiştim :) Diğer kullanıcıların görmesi için orada olması daha iyidir
Michael

Oh, bunun açık olduğunu düşündüm. Şimdi düzeltildi.
Jurij Pitulja

14

Ekim 2019'da yayınlanan Room 2.2.0'dan itibaren, güncellemeler için bir Hedef Varlık belirtebilirsiniz. Daha sonra güncelleme parametresi farklıysa, Oda yalnızca kısmi varlık sütunlarını güncelleyecektir. OP sorusu için bir örnek bunu biraz daha net gösterecektir.

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

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

Sorudaki gerçek Tur varlığınızla birlikte TourUpdate adlı yeni bir kısmi varlık oluşturmanız gerektiğine dikkat edin. Şimdi bir TourUpdate nesnesiyle güncellemeyi çağırdığınızda, endAddress'i güncelleyecek ve startAddress değerini aynı bırakacaktır. Bu, DAO'mda DB'yi API'den yeni uzak değerlerle güncelleyen ancak yerel uygulama verilerini tek başına tabloda bırakan bir insertOrUpdate yönteminin kullanım durumum için mükemmel çalışıyor.


6

Bunu deneyebilirsiniz, ancak performans biraz daha kötü olabilir:

@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

Yalnızca belirli bir alanı güncellemenize gerek olmadığını düşünüyorum. Sadece tüm verileri güncelleyin.

@Güncelleme sorgusu

Temelde verilen bir sorgudur. Yeni bir sorgu yapmaya gerek yok.

@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>?
)

Bilmeniz gereken tek şey 'id'. Örneğin, yalnızca 'başlığı' güncellemek istiyorsanız , önceden girilmiş verilerden 'içerik' ve 'fotoğraf'ı yeniden kullanabilirsiniz . Gerçek kodda böyle kullanın

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

-3

Belirli bir kullanıcı kimliği "x" için kullanıcı bilgilerini güncellemeniz gerekiyorsa,

  1. yapıcısında veritabanını başlatacak ve viewModel ile DAO arasında bir arabulucu görevi görecek ve ayrıca bir dbManager sınıfı oluşturmanız gerekir .
  2. ViewModel veritabanına erişim DBManager bir örneğini başlatır. Kod şu şekilde görünmelidir:

       @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);

    Ardından, kullanıcı öğenizi bu şekilde güncelleyin, kullanıcı kimliğinizin 1122 ve userName'in "zyx" olarak değiştirilmesi gereken "xyz" olduğunu varsayın.

    1122 Kullanıcı nesnesine ait bir userItem alın

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

Bu ham bir koddur, umarım size yardımcı olur.

Mutlu kodlama


10
Gerçekten bir görünüm modelinde veritabanları eylemi mi yapıyorsunuz ??? god no plz no ...: '(sadece model adını görün yüzünüze
çarpmalı

@mcfly, Görünüm Modelinde veritabanı işlemleri yapmak neden kötü kabul edilir?
Daniel

tek sorumluluk ilkesi bozuldu evet
mcfly
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.