it seems like hibernate merge was not meant for associating transient
objects to persistent
Merge is JPA standard - merges "new & detached entity instances" to "(persistence context-) managed entity instances". Will cascade across FK relationships marked Cascade.MERGE or Cascade.ALL.
From a JPA perspective - no, merge was not meant for associating your Xstream streamed transient objects to persistent. JPA intends for merge to work with the normal JPA lifecycle - create new objects, persistent them, get/find them, detach them, modify them (including adding new objects), merge them, optionally modifiy them some more, then persist/save them. This is deliberate design, so that JPA is stream-lined & performant - each individual object persist to the database doesn't need to be preceded with a retrieval of object state in order to determine whether/what to insert/update. The JPA persistence context object state already contains enough details to determine this.
Your problem is that you have new entity instances that you want to act as if they have been detached - and that's not the JPA way.
SaveOrUpdate is a hibernate proprietary operation - if an entity has an identity it is updated, but if it has not entity then it is inserted.
From a hibernate perspective - yes, merge followed by saveOrUpdate can theoretically work for associating (Xstream streamed) transient objects to persistent, but it may have restrictions when used in conjuction with JPA operations. saveOrUpdate DOES precede each object persist to the database with a retrieve to determine whether/what to insert/update - it's smart, but it's not JPA and it's not the most performant. i.e. you should be able to get this to work with some care and the right configuration - and using hibernate operations rather than JPA operations when conflict occurs.
I get errors such as:
org.hibernate.ObjectDeletedException: deleted object would be re-saved
by cascade (remove deleted object from associations):
[com.......SomeObject#353296]
I believe this might be caused by two factors:
- somewhere in your (Xstream-created) object graph, a child entity instance is missing that would be present if you did a (cascaded) retrieve using JPA: this gives an object deletion
somewhere else in you (Xstream-created) object graph, this same child entity is present: this gives the object being re-saved
How to debug this: (a) create the object graph from Xstream and print it out IN FULL - every entity, every field; (b) load the same object graph via JPA, cascading the retrieve from the top entity & print it out IN FULL - every entity, every field (c) compare the two - is something missing from (a) that is present in (b)??
Is there any way to achieve what I want to do without having to get
the persistent object in session, and modifying that, instead of
modifying the transient one, and trying to save that and override the
existing persistent one?
Via the debug/fix just suggested - hopefully.
OR my brute-force suggestion to (dumbly) side-step this bug (slows performance a little, though): after you populate IDs in the object graph, call EntityManager.clear(), THEN proceed with merge() and saveOrUpdate(). But UNIT TEST the DB results - to ensure you haven't overlooked something important in populating your Xstream graph.
For testing / as a last resort, try the saveOrUpdate() without the merge(), but you might then be forced to clear() the Entity manager to avoid Hibernate exceptions, such as NonUniqueObjectException.
Let me know if you learn more / have more info B^)