protected void entityIsDetached(MergeEvent event, Map copyCache) {
LOG.trace( "Merging detached instance" );
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final String entityName = persister.getEntityName();
Serializable id = event.getRequestedId();
if ( id == null ) {
id = persister.getIdentifier( entity, source );
}
else {
// check that entity id = requestedId
Serializable entityId = persister.getIdentifier( entity, source );
if ( !persister.getIdentifierType().isEqual( id, entityId, source.getFactory() ) ) {
throw new HibernateException( "merge requested with id not matching id of passed entity" );
}
}
String previousFetchProfile = source.getFetchProfile();
source.setFetchProfile( "merge" );
//we must clone embedded composite identifiers, or
//we will get back the same instance that we pass in
final Serializable clonedIdentifier = (Serializable) persister.getIdentifierType()
.deepCopy( id, source.getFactory() );
final Object result = source.get( entityName, clonedIdentifier );
source.setFetchProfile( previousFetchProfile );
if ( result == null ) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient( event, copyCache );
}
else {
( (EventCache) copyCache ).put( entity, result, true ); //before cascade!
final Object target = source.getPersistenceContext().unproxy( result );
if ( target == entity ) {
throw new AssertionFailure( "entity was not detached" );
}
else if ( !source.getEntityName( target ).equals( entityName ) ) {
throw new WrongClassException(
"class of the given object did not match class of persistent copy",
event.getRequestedId(),
entityName
);
}
else if ( isVersionChanged( entity, source, persister, target ) ) {
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatisticsImplementor()
.optimisticFailure( entityName );
}
throw new StaleObjectStateException( entityName, id );
}