I must have been mistaken about how Hibernate works. If all references are counted as the same object then the second test case I posted is rather strange behaviour. I think we'll start using flush and then detach as usual like you said, thanks @ryan2049 !
I believe that would make sense, even though you are attempting to query for a new instance, it is still going to return to you whatever is sitting in the hibernate session, so when you apply the detach, it will reset the state before the transaction is committed
I'm not certain why the detach > merge > detach > commit would work, somewhere along that line it must flush the changes before the detach reverts
I think a good rule of thumb here is that you should be flushing the session and committing the transaction before you attempt to detach the object
I just tried with a flush, after merging the updated object, isDirty becomes true. After flush, isDirty becomes false. However, if I update and merge, find the object again and do detach->merge->detach, isDirty is still true - so maybe it's not flushing after all.
@dcrn Your usage of #merge is technically incorrect.
Remember that #persist will take that instance of your bean, add it to the persistence context. #persist returns void because the same instance is used.
Now #merge on the other hand will not attach the instance passed, but instead constructs a new instance and adds it to the persistence context, optionally updating the state of the persistence context instance with that from the argument. Therefore when using #merge, you should use the return value after the fact to detach.
Anyway, I'll double check that there isn't an underlying bug anywhere but I wanted to point out that you should really make sure when using the #merge method that you're using the return value like as follows: