Update Opreation:
Box<User> testBox = App.getInstance().getBoxStore().boxFor(User.class);
User user = testBox.get(1);
user.setName("newName");
testBox.put(test);
Update opreation is NOT atomic.
If I delete data in one thread and update data in another thread then the deleted data might be save again
You are asking for transactions?
You are asking for transactions?
No.The transactions can not fit.
for(User user: allUsers) {
modify(user); //modifies user may take some time,what if the user has been deleted during modifying?
}
box.put(allUsers);//this will save the deleted user again
I see two basic approaches:
Wrap the loop and the put inside a write transaction. BUT, as you wrote the modification takes some time, this is probably not what you want, as write transactions should be short lived.
Unwrap the put of a list to a loop, which is executed in a write transaction. In the loop check if the element still exists.
for(User user: allUsers) {
modify(user); //modifies user may take some time
}
boxStore.runInTx(() -> {
for(User user: allUsers) {
User existing = box.get(user.getId()); // null if deleted
if(existing != null) box.put(user);
}
}
Solution 2 sounds great,thanks for your advice.
AFAIK,The transactions is used to ensure the whole wrapped block is atomic.Is it thread safe?
boxStore.runInTx(() -> {
for(User user: allUsers) {
User existing = box.get(user.getId()); // not null here
//current thread got paused and this user was deleted by other thread
//what will happen when current thread got resumed?
if(existing != null) box.put(user);
}
}
ObjectBox in itself is intended to be tread safe, so are transactions. There are a couple of rules, e.g.:
Transactions are tied to threads
There can be a single write transaction at any time (consider it a lock)
Read transactions never get blocked or block a write transaction
Thus, you could use write transactions to enforce code to run strictly sequentially.
P.S.: the entire code block passed to runInTx() runs inside a write transaction; there's no way another write transaction can interfere until it's done.
Thanks for all of this.
Update: 2.7.0 adds Box.contains(id) which is less expensive than Box.get() != null.
Anyhow, is this a bug with put(entity)? Shouldn't it do nothing or error if putting an entity with non-zero ID where that entity does not (longer) exist? (Assuming @Id is left at default auto-assigned.)
A put() always puts; so "works as intended" :smile:. However, at core and C level, we actually have put modes (e.g. update/insert) for finer control. At some time we'll bubble that up to Java...