Currently, I'm using the solution with flushmode = MANUAL, which after my tests I feel is the most elegant one;
but it would be nice to be able to use the standard flushmode instead,
and just somehow tell the EntityManager "ok, the validation failed, so don't do anything after returning from this method".
Oh, how I wished that there would be a clean solution for this.
I think the best (even if cumbersome) way to do this is the last topic in your "DON't want" list:
"validator method on a hidden input and extract all input values from the component tree". That way the local component values never would make it into the entity model.
We should really blame JSF for this. There simply should be some dedicated way to have multi-component/form-level validations.
I recently had to correct a bug in production that occurred because some developer not that accustomed to Seam and hibernate added validation code to an action handler and was not aware of automatic flushing. (My dirty fix was to use setRollbackOnly, because no long running conversation was active anyway.)
There is another (cumbersome) solution that is missing in you list:
Over the time I found that dedicated value objects should not be abandoned completely, but do sometimes make life easier:
- When the GUI design differs sufficiently from the entity model, then they are the way to go anyway.
- They avoid issues like the one you are describing.
- Developers without much experience in hibernate and seam do not need to wrap their minds around the intricate (even though sensible) way a persistence context, long and short conversations, and transactions interact.
A little more work to copy data, less bugs. Every decent IDE will help you create DTOs quickly.
BTW: AFAICS there is no automatic "merge" as you thread title suggests.
There are a few different solutions to this:
1) Back your pages with entity beans, use MANUAL flush mode with a conversation, flush() when you want.
2) Back your pages with DTOs. Apply the changes to the entities from the DTOs when you want.
3) Back your pages with entity beans, but after you find the entities, evict them from the entity manager. Merge them when you want to update. This is fraught with danger if you have lazy relationships.
4) Don't use the SeamPersistenceContext ( @In entityManager ) and control the transactions yourself using the EJB3 @PersistenceContext.
We have a fairly large SEAM application and have struggled with this, but solution 1 has worked well for us.
Our SEAM app is also of significant size, and Cory's solution 1 also works for us.
However, according to the documentation (section 9.3.3 of the seam reference for 2.0.2.sp1) only hibernate supports MANUAL flushmode, so if you use other JPA providers, you are out of luck.