简体   繁体   中英

JPA: Extending the persistence context vs. detaching entities

There appear to be two patterns to implement business transactions that span several http requests with JPA:

  1. entity-manager-per-request with detached entities
  2. extended persistence context

What are the respective advantages of these patterns? When should which be preferred?

So far, I came up with:

  • an extended persistence context guarantees that object identity is equivalent to database identity, simplifying the programming model and potentially disspelling the need to implement equals for entities
  • detached entities require less memory than an extended persistence context, as the persistence context also has to store the previous state of the entity for change detection
  • no longer referenced detached entities become eligible for garbage collection; persistent objects must first be detached explicitly

However, not having any practical experience with JPA I am sure I have missed something of importance, hence this question.

In case it matters: We intend to use JPA 2.0 backed by Hibernate 3.6.

Edit : Our view technology is JSF 2.0, in an EJB 3.1 container, with CDI and possibly Seam 3.

Well, I can enumerate challenges with trying to use extended persistence contexts in a web environment. Some things also depend on what your view technology is and if it's binding entities or view level middlemen.

  1. EntityManagers are not threadsafe. You don't need one per user session. You need one per user session per browser tab.
  2. When an exception comes out of an EntityManager, it is considered invalid and needs to be closed and replaced. If you're planning to write your own framework extensions for managing the extended lifecycle, the implementation of this needs to be bullet proof. Generally in an EM-per-request setup the exception goes to some kind of error page and then loading the next page creates a new one anyway like it always would have.
  3. Object equality is not going to be 100% automagically safe. As above, an exception may have invalidated the context an object loaded earlier was associated with, so one fetched now will not be equal. Making that assumption also assumes an extremely high level of skill and understanding of how JPA works and what the EM does among the developers using it. eg, accidentally using merge when it wasn't needed will return a new object which will not satisfy == with its field-identical predecessor. (treating merge like a SQL 'update' is an extremely common JPA noobie 'error' particularly because it's just a no-op most of the time so it slides past.)
  4. If you're using a view technology that binds POJOs (eg, SpringMVC) and you're planning to bind web form data directly onto your Entities, you'll get in trouble quick. Changes to an attached entity will become persistent on the next flush/commit, regardless of whether they were done in a transaction or not. Common error is, web form comes in and binds some invalid data onto an entity, validation fails and trys to return a screen to inform user. Building error screen involves running a query. Query triggers flush/commit of persistence context. Changes bound to attached entity get flushed to database, hopefully causing SQL exception, but maybe just persisting corrupt data.

(Problem 4 can of course also happen with session per request if the programming is sloppy, but you're not forced to actively work hard at avoiding it.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM