Hibernate thread-safe idempotent upsert without constraint exception handling?
Short answer - Hibernate does not support it out of the box (as confirmed by a Hibernate guru in this blog post). Probably you could make it work to some extent in some scenarios with the mechanisms you already described, but just using native queries directly looks the most straightforward approach to me for this purpose.
Longer answer would be that it would be hard to support it considering all the aspects of Hibernate I guess, e.g.:
- What to do with instances for which duplicates are found, as they are supposed to become managed after persisting? Merge them into persistence context?
- What to do with associations that have already been persisted, which cascade operations to apply on them (persist/merge/something_new; or is it too late at that point to make that decision)?
- Do the databases return enough info from upsert operations to cover all use cases (skipped rows; generated keys for not-skipped in batch insert modes, etc).
- What about
@Audit
-ed entities, are they created or updated, if updated what has changed? - Or versioning and optimistic locking (by the definition you actually want exception in that case)?
Even if Hibernate supported it in some way, I'm not sure I'd be using that feature if there were too many caveats to watch out and take into consideration.
So, the rule of thumb I follow is:
- For simple scenarios (which are most of the time): persist + retry. Retries in case of specific errors (by exception type or similar) can be globally configured with AOP-like approaches (annotations, custom interceptors and similar) depending on which frameworks you use in your project and it is a good practice anyway especially in distributed environments.
- For complex scenarios and performance intensive operations (especially when it comes to batching, very complex queries and alike): Native queries to maximize utilization of specific database features.