JPA confusion (managed vs non-managed entities)

十年热恋 提交于 2019-11-29 14:14:59

问题


I'm working on a web project, trying to understand the best way to do this sort of thing over and over again:

  • Read object A from the DB
  • Later on, read another object (B)
  • Make changes to A and B in the DB (as part of a transaction - write all the changes or none)

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.


回答1:


  1. 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.

  2. 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.

  3. The flush in example 2 is not really needed, the commit will implicitly flush.

  4. 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.

  5. 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.

  6. 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.

  7. 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.




回答2:


With regards to your fourth question, rollback can be done by the following approaches:

  1. Throw an exception from the method that is marked as @Transactional
  2. Tell the transaction explicitly that it should rollback by TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();


来源:https://stackoverflow.com/questions/7434115/jpa-confusion-managed-vs-non-managed-entities

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!