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

我正在使用 android Room 持久性库来完成我的新项目。 我想更新一些表格字段。 我已经试过像在我的 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);

它正在工作,但是在我的情况下会有许多查询,因为我的实体中有许多字段。我想知道如何更新一些字段(不是全部) ,比如 id = 1的 Method 1; (id 是自动生成的主键)。

// Entity:


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

我想知道如何更新一些字段(不是全部) ,比如方法1,其中 id = 1

使用 @Query,就像您在方法2中所做的那样。

在我的例子中是太长的查询,因为在我的实体中有许多字段

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

房间里没有任何东西可以满足你的需求。

房间现在有部分实体支持,这可以帮助这个场景。请参阅 这个答案了解更多。

根据 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);
}

如果需要更新特定用户 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”。

    获取一个 userItem of id 1122 User object

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

这是原始代码,希望对你有所帮助。

编程愉快

你可以试试这个,但性能可能会差一点:

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

从2019年10月发布的 2.2.0房间开始,您可以为更新指定一个目标实体。然后,如果更新参数不同,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;
}

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

我认为你不需要仅仅更新一些特定的字段。 只需更新整个数据

@ 更新查询

它基本上是一个给定的查询,不需要做一些新的查询。

@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”。例如,如果只想更新“ title”,可以从已插入的数据中重用“ content”和“ photo”< strong > 。 在实际代码中,使用如下

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

在我自己试图解决一个类似的问题之后,我把 @PrimaryKey(autoGenerate = true)改成了 int UUID,我找不到如何写我的迁移,所以我改变了表名,这是一个简单的解决方法,如果你使用一个个人/小型应用程序,没问题

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

您还应该将其添加到更新方法 OnSymphtStrategy 中

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