I’m using Play Framework and I have what I think is a very frequent persistence problem :
- I display a form with values coming from the database and a field ‘quantity’
- The user updates the form and changes the ‘quantity’ value
- He clicks on the “save button”
- In the controller method called, I want to get the old value of ‘quantity’ and calculate the difference between the new and the old one before updating the DB
- To make that, i use findById (before calling the object.save method), but it gives me the new value, not the old one : it apparently looks into some cache (which one ?) instead of requesting the DB
=> is that a normal ? how can i get the old value, make my calculation and then persist ?
Thanks a lot for your help, I do not want to manage old/new value in my DB…i’m sure it’s bad practice !
UPDATE
public static void save(@Valid Lot lot) {
History element = new History();
element.date = new Date();
//HERE below it returns the new value, not the old one
Lot databaseLot = Lot.findById(lot.id);
element.delta= databaseLot.quantity - lot.quantity;
element.save();
lot.save();
list(null, null, null, null);
}
This is because, Play is doing some magic for you here.
When you pass a JPA Object into your controller, that contains an ID, Play will automatically retrieve this JPA Object from the database. If you look here, it explains this in a little more detail. It states (and assuming an action call that is passing in a User JPA Pojo)
So, how can you fix this? I guess the easiest way is to not pass the id as part of the Pojo Object, and to pass the ID as a separate parameter, therefore Play will believe the object is not required to be automagically retrieved from the database.
An alternative method, is to have a setter method for the quantity field, which updates the delta. So, Play will automatically retrieve the object from the DB, then call your setter method to update the values (as per normal POJO binding), and as part of that operation, your new quantity, and the delta are set. Perfect! This is the best option in my opinion as it also ensures that the business logic stays neatly inside of your Model, and not your Controller.