I am writing a JSF 2.0 form to edit a JPA @Entity object. I have a backing bean that has a get method for the Entity, which it fetches from the EntityManager. So far so good.
The question is does the Entity object that is开发者_运维知识库 being edited by the user get accessed by other parts of the application? In other words if someone else calls up that record, do they see the field changes before I merge the record back into the data base via the EntityManager? Or do they get a different instance.
The reason this is important is that the user can enter all sorts of bad data. The validation phase done by the backing bean will not call merge() all the errors are cleared, but what about before then?
If this is a common instance, how do I avoid this problem?
The question is does the Entity object that is being edited by the user get accessed by other parts of the application? In other words if someone else calls up that record, do they see the field changes before I merge the record back into the data base via the EntityManager? Or do they get a different instance.
The entity instance used by JSF will be a detached entity instance. It is not one that belongs to the persistence context. Each client/user will also receive it's own instance of the detached entity.
The reason this is important is that the user can enter all sorts of bad data. The validation phase done by the backing bean will not call merge() all the errors are cleared, but what about before then?
The merging of any invalid data will occur on when you invoke EntityManager.merge
to merge the contents of the detached entity with the persistence context. If you never invoked merge
, then the modified contents of the Entity will never make it to the persistence context.
If this is a common instance, how do I avoid this problem?
You can always avoid this by validating the state of the entity before merging it with the persistence context. You could employ bean validation in both JSF and JPA, to prevent this scenario, although you will typically do this only in one layer, to prevent redundant checks. However, if you have specified validation groups for your bean validation constraints to distinguish between presentation and persistence constraints, then you ought be employing bean validation in both the layers. Do keep in mind, that once the contents of the bean have been merged successfully with the persistence context, there isn't a lot you can do to undo this change, except for a transaction rollback, or a refresh
/clear
of the persistence context.
Adding to the correct answer of Vineet:
You could possibly have an attached entity returned by your backing bean, for instance if you used a stateful session bean (EJB) with the extended persistence context.
In this case however you would still not risk concurrency issues, since every instance of a persistence context returns unique instances of attached entities (unique: instance not shared with other existing persistence contexts).
Furthermore, JSF will not push changes into the model (the attached JPA entity in this case) if any kind of validation error occurs. So as long as you have your validation set up correctly (bean validation or regular JSF validation), there will be no risk of 'tainting' the entity.
Additionally, note that for the attached case you would not have to call merge()
, as this will automatically happen when the context closes, so instead you 'close' the stateful bean.
That said, the common case is the one Vineet describes where you get a detached entity.
精彩评论