momalito
momalito

Reputation: 55

Calculation before db update

I'm using Play Framework and I have what I think is a very frequent persistence problem :

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

Upvotes: 2

Views: 542

Answers (3)

Arasu
Arasu

Reputation: 2148

You may save quantity value in a hidden text and you can process that

Upvotes: 0

Codemwnci
Codemwnci

Reputation: 54914

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)

You can automatically bind a JPA object using the HTTP to Java binding.

You can provide the user.id field yourself in the HTTP parameters. When Play finds the id field, it loads the matching instance from the database before editing it. The other parameters provided by the HTTP request are then applied. So you can save it directly.

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.

Upvotes: 3

Mac
Mac

Reputation: 1642

I can't speak to the Play Framework specifically, but in JPA, the EntityManager caches objects for it's lifetime, unless explicitly emptied. Because of that, querying for an object that the context is already managing will just give you the cached version. Furthermore, it sounds like the EM you are getting is declared as EXTENDED, which causes the same EM to be used across multiple requests (or perhaps the framework does the lookup under the covers and sets the values before you get to handle it).

You will either need to work around this cache or configure Play to use a TRANSACTION-scoped Persistence Context (aka EntityManager). I can't help you with the latter, but the former is easy enough.

int newQuantity = entity.getQuantity();
entityManager.refresh(entity);
// enity.getQuantity() should now give you the old value
// Do your calculation
// entity.setQuantity(newQuantity);

At the end of the transaction, your new state should be saved.

Upvotes: 0

Related Questions