在android Room中更新实体的某些特定字段

时间:2017-08-21 04:29:02

标签: android sql-update android-room

我正在为我的新项目使用android房间持久性库。 我想更新一些表的字段。 我在我的Dao -

中尝试过
// Method 1:

@Dao
public interface TourDao {
    @Update
    int updateTour(Tour 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
}

9 个答案:

答案 0 :(得分:38)

  

我想知道如何更新某些字段(并非所有字段),例如方法1,其中id = 1

使用@Query,就像在方法2中一样。

  在我的情况下,

查询太长了,因为我的实体中有很多字段

然后有更小的实体。或者,不要单独更新字段,而是与数据库进行更粗粒度的交互。

IOW,房间本身没有什么可以做你想要的。

答案 1 :(得分:38)

根据SQLite Update Docs

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

/**
* 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);
}

答案 2 :(得分:32)

Room 2.2.0到2019年10月发布,您可以指定目标实体进行更新。然后,如果update参数不同,Room将仅更新部分实体列。一个关于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;
}

请注意,您必须与问题中的真实Tour实体一起创建一个名为TourUpdate的新部分实体。现在,当您使用TourUpdate对象调用update时,它将更新endAddress并使startAddress值保持不变。对于我在DAO中使用insertOrUpdate方法的用例来说,这非常适合我,该方法用API中的新远程值更新数据库,但将本地应用程序数据保留在表中。

答案 3 :(得分:3)

我认为您不需要仅更新某些特定字段。 只需更新整个数据即可。

@更新查询

基本上是给定查询。无需重新查询。

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

您只需要知道'id'。例如,如果您只想更新“标题”,则可以从已经插入的数据中重用“内容”和“照片”。 在真实的代码中,像这样使用

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

答案 4 :(得分:2)

也许您可以尝试一下,但是性能会稍差一些(或更多):

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

答案 5 :(得分:0)

我们需要您要更新的特定模型的主键。 例如:

 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为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

答案 6 :(得分:0)

您可以使用 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);

答案 7 :(得分:-1)

在尝试解决我自己的类似问题后,我已将 @PrimaryKey(autoGenerate = true) 更改为 int UUID,但找不到如何编写迁移,因此我更改了表名,这很简单修复,如果您使用个人/小型应用程序就可以了

答案 8 :(得分:-2)

如果您需要更新特定用户ID“x”的用户信息,

  1. 您需要创建一个 dbManager 类,该类将在其构造函数中初始化数据库,并充当viewModel和DAO之间的中介,以及。
  2. ViewModel 将初始化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用户对象

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

    这是一个原始代码,希望它可以帮到你。

    快乐编码