I am using android room persistence library for my new project.
I want to update some field of table.
I have tried like in my Dao
-
// Method 1
I want to know how can I update some field(not all) like method 1 where id = 1
Use @Query
, as you did in Method 2.
is too long query in my case because I have many field in my entity
Then have smaller entities. Or, do not update fields individually, but instead have more coarse-grained interactions with the database.
IOW, there is nothing in Room itself that will do what you seek.
UPDATE 2020-09-15: Room now has partial entity support, which can help with this scenario. See this answer for more.
We need the primary key of that particular model that you want to update. For example:
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))
}
In this function, I am checking whether a particular entry exists in the database if exists pull the primary key which is id over here and perform update function.
This is the for fetching and update records:
@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
According to 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);
Example:
Entity:
@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);
}
As of Room 2.2.0 released October 2019, you can specify a Target Entity for updates. Then if the update parameter is different, Room will only update the partial entity columns. An example for the OP question will show this a bit more clearly.
@Update(entity = Tour::class)
fun update(obj: TourUpdate)
@Entity
public class TourUpdate {
@ColumnInfo(name = "id")
public long id;
@ColumnInfo(name = "endAddress")
private String endAddress;
}
Notice you have to a create a new partial entity called TourUpdate, along with your real Tour entity in the question. Now when you call update with a TourUpdate object, it will update endAddress and leave the startAddress value the same. This works perfect for me for my usecase of an insertOrUpdate method in my DAO that updates the DB with new remote values from the API but leaves the local app data in the table alone.
If you need to update user information for a specific user ID "x",
The ViewModel will initialize an instance of dbManager to access the database. The code should look like this:
@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);
Then just update your user item this way, suppose your userId is 1122 and userName is "xyz" which has to be changed to "zyx".
Get an userItem of id 1122 User object
User user = new user(); if(user.getUserId() == 1122){ user.setuserName("zyx"); userViewModel.updateUser(user); }
This is a raw code, hope it helps you.
Happy coding
You could try this, but performance may be worse a little:
@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);
}
}