I'm working on a web project, trying to understand the best way to do this sort of thing over and over again:
The old-skool JDBC-type way isn't a problem, but JPA is doing my head in.
I need there to be a clear demarcation as to where the DB changes occur, and from what I've observed any changes to managed entities will be modified the next time EntityManager.commit()
is called (no matter if a transaction was explicitly begun before the changes or not). Correct?
Is it better then to make sure all entities are never managed, and always merge()
?
I find myself having to decide between these two examples:
RepaintAction1
User user = getUser(); //non-managed entity
Car car = getCar(123); //non-managed
car.setColor("Red");
user.setLog("Paints car red");
dao.update(car, user);
RepaintDAO1
entityTransaction.begin();
entityManager.merge(car);
entityManager.merge(user);
entityTransaction.commit();
Or:
RepaintAction2 (this is the same as RepaintAction1, but with managed entities)
User user = getUser(); //managed entity
Car car = getCar(123); //managed
car.setColor("Red");
user.setLog("Paints car red");
dao.update(car, user);
RepaintDAO2
entityTransaction.begin();
entityManager.flush();
entityTransaction.commit();
The first I don't mind, but I must be missing some advantages to managed entities (which ones?). In the second I don't like the way the scope of transactions is not clear (and how is a rollback handled?).
But are these the only options (e.g. is there a way to clearly demarcate transactions using managed entities)? What is the best way to handle this?
I apologise for making this long, but I've gone through a lot of documentation that hasn't helped and I'm not even sure that what I'm observing is correct.
Any changes to managed entities will be modified the next time EntityManager.commit()
is called (no matter if a transaction was explicitly begun before the changes or not). Correct?
Correct.
Is it better then to make sure all entities are never managed, and always merge()
?
Not always (or they would not leave the choice open) but it is common,
so example 1 is what you'll find mostly.
The flush in example 2 is not really needed, the commit will implicitly flush.
How is rollback handled? If the commit fails, the persistence provider will roll back. An application container will rollback existing transactions if it receives a system exception.
Advantages of managed entities? Lazy loading (no LazyInitializationException). Also it keeps track of what's changed for you, so you do not merge too much/few entities.
Is there a way to clearly demarcate transactions using managed entities? It is not clear to me what is not clear to you. Maybe you mean that it is not clear to see what has changed because the changes to the entities happen outside the begin/commit boundaries. But that's true for merging detached entities as well, you have a little more control over what you merge, but you do not see exactly which attributes are changed.
What's the best way to handle this? Typically your web requests are handled by a service that is transactional (spring/ejb...). Entity managers will be injected by the container. Typically these Entity managers are transaction scoped (only live for the time of the transaction), so they did not exist before your service was called. This implies that all entities passed to them are not managed. The transaction will commit (or roll back) at the end of the service.
Note: if you think about using managed entities this often goes with long lived EntityManagers. If you do this, mind that EntityManagers are not thread safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With