protected Object mergeTransientEntity(Object entity, String entityName, Serializable requestedId, EventSource source, Map copyCache) {
log.trace("merging transient instance");
final EntityPersister persister = source.getEntityPersister( entityName, entity );
final Serializable id = persister.hasIdentifierProperty() ?
persister.getIdentifier( entity, source.getEntityMode() ) :
null;
if ( copyCache.containsKey( entity ) ) {
persister.setIdentifier( copyCache.get( entity ), id, source.getEntityMode() );
}
else {
( ( EventCache ) copyCache ).put( entity, persister.instantiate( id, source.getEntityMode() ), true ); //before cascade!
//TODO: should this be Session.instantiate(Persister, ...)?
}
final Object copy = copyCache.get( entity );
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
super.cascadeBeforeSave(source, persister, entity, copyCache);
copyValues(persister, entity, copy, source, copyCache, ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT);
try {
//this bit is only *really* absolutely necessary for handling
//requestedId, but is also good if we merge multiple object
//graphs, since it helps ensure uniqueness
if (requestedId==null) {
saveWithGeneratedId( copy, entityName, copyCache, source, false );
}
else {
saveWithRequestedId( copy, requestedId, entityName, copyCache, source );
}
}
catch (PropertyValueException ex) {
String propertyName = ex.getPropertyName();
Object propertyFromCopy = persister.getPropertyValue( copy, propertyName, source.getEntityMode() );
Object propertyFromEntity = persister.getPropertyValue( entity, propertyName, source.getEntityMode() );
Type propertyType = persister.getPropertyType( propertyName );
EntityEntry copyEntry = source.getPersistenceContext().getEntry( copy );
if ( propertyFromCopy == null || ! propertyType.isEntityType() ) {
log.trace( "property '" + copyEntry.getEntityName() + "." + propertyName +
"' is null or not an entity; " + propertyName + " =["+propertyFromCopy+"]");
throw ex;