views:

483

answers:

1

Hi!

We are running JBoss with Hibernate and are having this issue.

When a session bean uses an EntityManager to find an entity, it may already exist in the EntityManager's cache and it's state may be already outdated. If the code uses such an entity to make decisions, it may make wrong decisions that would produce bugs.

Here is an example case.

HTTP request 1. A session bean creates an entity instance and stores it with field "A" set to value 1. The persisted entity gets ID = 4.

HTTP request 2. A session bean looks up an entity with ID = 4, sets its field "A" to value 2 and saves it.

HTTP request 3. A session bean looks up an entity with ID = 4 and checks it's field "A". If the value is 1 it does one thing, if it is 2 it does another thing.

In case if the EM in request 3 happens to be the same as in request 1, an undesired behavior occurs. I have tested this and got approx. 10% cases of failure.

So the question is - how to avoid this? Calling em.refresh() or em.clear() each time I have to ensure the entity is up to date seems to be a waste of resources.

+1  A: 

Artem,

This seems to be a recurring theme among your questions :-)

While I understand that answers you've been given before (including mine) may not be what you were hoping for, they're not going to change:

  • Entity Manager is a mapped to Hibernate session and generally needs to be short-lived. Here is a good explanation of unit of work, transaction and scope pertaining to Hibernate sessions, take a look if you haven't seen it before.
  • If your application is consistently holding on to Entity Managers, you need to seriously consider changing that strategy; if you're just doing it in a few places where you really need to have long transactions than using refresh() method there is definitely the lesser of all evils.
  • Unlike the second level cache which has clustered implementations, session-level cache is not synchronized among diferent sessions (entity managers) by design and concurrent updates to the same entity are handled via optimistic locking provided by Hibernate or application-level locking.
  • You could in theory (provided your ORM access is separated well enough) maintain your own cache (clusterable if needed) of entities held by various Entity Managers; you would need to register appropriate event listeners with each to keep your cache in sync. I would strongly advice against this approach, though - not only it's rather involved to implement and bug-prone, but you'd be going against Hibernate's paradigm with this.
ChssPly76
Thank you for your patience and helpfulness. I realized I have been asking the wrong questions all the time. Here is what I really ment: http://stackoverflow.com/questions/1293429/how-to-force-jboss-4-2-3-to-clear-hibernates-session-cache-for-every-request. Sorry for being such a moron.
artemb
There's nothing moronic about your questions - the whole session cache thing is quite confusing :-) I've left a comment in the above question, perhaps it will help - I'm not using CMP myself so I'm not quite sure how to change entity manager scope; it's definitely a configuration / deployment issue, though - I'm sure somebody will answer your question. Good luck with your implementation.
ChssPly76