My last comment was nonsense, please ignore it.
Here is a simple test-case for reproducing this problem.
Code:
// Get a theme
Theme theme = DefaultTheme.getRoot(session);
// Get a child theme
Theme childTheme = (Theme) theme.getChildren().iterator().next();
// Evict it
Serializable id = session.getIdentifier(childTheme);
session.evict(childTheme);
// Reload the child
childTheme = (Theme) session.get(childTheme.getClass(), id);
// This throws: "org.hibernate.NonUniqueObjectException: a different object
// with the same identifier value was already associated with the session"
// because the parent is still pointing to the old child. At flushing time,
// it cascades saveOrUpdate() on the old child but the session already has
// the new child (with the same id) associated with the session.
session.flush();
Now, in-so-far as I see it this is something that should be fixed inside Hibernate. Either evict() should uninitialize references to evicted objects inside associations or -- probably easier -- Session.get() should be modified to reuse these preexisting detached instances.
With the current implementation it doesn't look like there is any reasonable workaround for users to use. It is completely possible that code in one place will evict() while completely unrelated code in another place will Session.get(). Session.contains() will not help here either.
Is there another API or workaround I am overlooking? I welcome your feedback.
Gili