sourcecode

Android Room에서 엔티티의 특정 필드를 업데이트합니다.

copyscript 2023. 8. 7. 22:53
반응형

Android Room에서 엔티티의 특정 필드를 업데이트합니다.

저는 새로운 프로젝트를 위해 안드로이드 룸 지속성 라이브러리를 사용하고 있습니다.테이블 필드를 업데이트하려고 합니다.나는 내 삶에서 처럼 노력해왔습니다.Dao-

// Method 1:

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

그러나 이 방법을 사용하여 업데이트를 시도하면 둘러보기 개체의 기본 키 값과 일치하는 엔티티의 모든 필드가 업데이트됩니다.사용한 적이 있습니다.@Query

// Method 2:

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

작동하고 있지만, 제 경우에는 엔티티에 많은 필드가 있기 때문에 많은 문의가 있을 것입니다.일부 필드(모두가 아님)를 업데이트하는 방법을 알고 싶습니다.Method 1여기서 id = 1; (id는 자동 생성 기본 키입니다.)

// Entity:

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

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

예:

엔티티:

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

2019년 10월에 공개된 룸 2.2.0부터는 업데이트 대상 엔티티를 지정할 수 있습니다.업데이트 매개변수가 다른 경우, 룸은 부분 도면요소 열만 업데이트합니다.OP 질문의 예는 이것을 좀 더 명확하게 보여줄 것입니다.

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

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

질문에 포함된 실제 둘러보기 엔터티와 함께 TourUpdate라는 새 부분 엔터티를 만들어야 합니다.이제 TourUpdate 개체로 업데이트를 호출하면 endAddress가 업데이트되고 startAddress 값은 동일하게 유지됩니다.이것은 API의 새 원격 값으로 DB를 업데이트하지만 로컬 앱 데이터는 테이블에 그대로 두는 DAO의 insertOrUpdate 메서드 사용 사례에 적합합니다.

방법 1과 같은 일부 필드(전부가 아님)를 업데이트하는 방법을 알고 싶습니다(ID = 1).

사용하다@Query방법 2에서 했던 것처럼.

내 경우에는 너무 긴 쿼리입니다. 왜냐하면 내 엔티티에 많은 필드가 있기 때문입니다.

그런 다음 더 작은 개체를 만듭니다.또는 필드를 개별적으로 업데이트하지 않고 데이터베이스와 더 거친 상호작용을 수행합니다.

IOW, 방 자체에는 당신이 원하는 것을 할 수 있는 어떤 것도 없습니다.

업데이트 2020-09-15: Room은 이제 부분 엔티티 지원을 제공하여 이 시나리오에 도움이 될 수 있습니다.자세한 내용은 이 답변을 참조하십시오.

사용해 볼 수 있지만 성능이 조금 더 나빠질 수 있습니다.

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

특정 필드만 업데이트할 필요는 없다고 생각합니다.전체 데이터만 업데이트하면 됩니다.

@업데이트 쿼리

기본적으로 주어진 쿼리입니다.새로운 쿼리를 만들 필요가 없습니다.

@Dao
interface MemoDao {

    @Insert
    suspend fun insert(memo: Memo)

    @Delete
    suspend fun delete(memo: Memo)

    @Update
    suspend fun update(memo: Memo)
}

메모 클래스

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

당신이 알아야 할 것은 'id'입니다.예를 들어 '제목'만 업데이트하려는 경우 이미 삽입된 데이터에서 '내용'과 '사진'을 다시 사용할 수 있습니다.실제 코드에서는 다음과 같이 사용합니다.

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

업데이트할 특정 모델의 기본 키가 필요합니다.예:

 private fun update(Name: String?, Brand: String?) {
    val deviceEntity = remoteDao?.getRemoteId(Id)
    if (deviceEntity == null)
        remoteDao?.insertDevice(DeviceEntity(DeviceModel = DeviceName, DeviceBrand = DeviceBrand))
    else
        DeviceDao?.updateDevice(DeviceEntity(deviceEntity.id,remoteDeviceModel = DeviceName, DeviceBrand = DeviceBrand))
}

이 기능에서는 데이터베이스에 특정 항목이 있는지 확인하고 있습니다. 만약 존재한다면 id인 기본 키를 여기로 당겨서 업데이트 기능을 수행합니다.

레코드 가져오기 및 업데이트는 다음과 같습니다.

@Query("SELECT * FROM ${DeviceDatabase.DEVICE_TABLE_NAME} WHERE ${DeviceDatabase.COLUMN_DEVICE_ID} = :DeviceId LIMIT 1")

fun getRemoteDeviceId(DeviceId: String?): DeviceEntity


@Update(onConflict = OnConflictStrategy.REPLACE)
fun updatDevice(item: DeviceEntity): Int

URI를 사용하여 데이터베이스의 행을 ID별로 업데이트할 수 있습니다.

Tour tourEntity = new Tour();
tourEntity.end_address = "some adress";
tourEntity.start_address= "some adress";
//tourEntity..... other fields
tourEntity.id = ContentUris.parseId(Uri.parse("content://" + BuildConfig.APPLICATION_ID + File.separator + id));
//get your updatemethod with abstract func in your database class (or with another way, wich you use in project)
int tourDaoUpdate = getInstance(context).tour().update(tourEntity);

또한 업데이트 방법 OnConflictStrategy에 추가해야 합니다.

@Update(onConflict = OnConflictStrategy.REPLACE)
int updateTour(Tour tour);

특정 사용자 ID "x"에 대한 사용자 정보를 업데이트해야 하는 경우,

  1. 생성자에서 데이터베이스를 초기화하고 viewModel과 DAO 사이의 중재자 역할을 하는 dbManager 클래스를 만들어야 합니다.
  2. View Model은 데이터베이스에 액세스하기 위해 dbManager 인스턴스를 초기화합니다.코드는 다음과 같아야 합니다.

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

    그런 다음 userId가 1122이고 userName이 "xyz"이며 "zyx"로 변경되어야 한다고 가정할 때, 이러한 방법으로 사용자 항목을 업데이트하십시오.

    ID 1122의 userItem 사용자 개체 가져오기

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

이것은 원시 코드입니다. 도움이 되길 바랍니다.

해피 코딩

언급URL : https://stackoverflow.com/questions/45789325/update-some-specific-field-of-an-entity-in-android-room

반응형