FileDocCategorySizeDatePackage
DefaultReplicateEventListener.javaAPI DocHibernate 3.2.56202Wed Jan 24 07:29:44 GMT 2007org.hibernate.event.def

DefaultReplicateEventListener

public class DefaultReplicateEventListener extends AbstractSaveEventListener implements org.hibernate.event.ReplicateEventListener
Defines the default replicate event listener used by Hibernate to replicate entities in response to generated replicate events.
author
Steve Ebersole

Fields Summary
private static final Log
log
Constructors Summary
Methods Summary
private voidcascadeAfterReplicate(java.lang.Object entity, org.hibernate.persister.entity.EntityPersister persister, org.hibernate.ReplicationMode replicationMode, org.hibernate.event.EventSource source)

		source.getPersistenceContext().incrementCascadeLevel();
		try {
			new Cascade( CascadingAction.REPLICATE, Cascade.AFTER_UPDATE, source )
					.cascade( persister, entity, replicationMode );
		}
		finally {
			source.getPersistenceContext().decrementCascadeLevel();
		}
	
protected org.hibernate.engine.CascadingActiongetCascadeAction()

		return CascadingAction.REPLICATE;
	
protected booleanisVersionIncrementDisabled()

		return true;
	
public voidonReplicate(org.hibernate.event.ReplicateEvent event)
Handle the given replicate event.

param
event The replicate event to be handled.
throws
TransientObjectException An invalid attempt to replicate a transient entity.


	                       	 
	    
		final EventSource source = event.getSession();
		if ( source.getPersistenceContext().reassociateIfUninitializedProxy( event.getObject() ) ) {
			log.trace( "uninitialized proxy passed to replicate()" );
			return;
		}

		Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );

		if ( source.getPersistenceContext().isEntryFor( entity ) ) {
			log.trace( "ignoring persistent instance passed to replicate()" );
			//hum ... should we cascade anyway? throw an exception? fine like it is?
			return;
		}

		EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );

		// get the id from the object
		/*if ( persister.isUnsaved(entity, source) ) {
			throw new TransientObjectException("transient instance passed to replicate()");
		}*/
		Serializable id = persister.getIdentifier( entity, source.getEntityMode() );
		if ( id == null ) {
			throw new TransientObjectException( "instance with null id passed to replicate()" );
		}

		final ReplicationMode replicationMode = event.getReplicationMode();

		final Object oldVersion;
		if ( replicationMode == ReplicationMode.EXCEPTION ) {
			//always do an INSERT, and let it fail by constraint violation
			oldVersion = null;
		}
		else {
			//what is the version on the database?
			oldVersion = persister.getCurrentVersion( id, source );			
		}

		if ( oldVersion != null ) { 			
			if ( log.isTraceEnabled() ) {
				log.trace(
						"found existing row for " +
								MessageHelper.infoString( persister, id, source.getFactory() )
				);
			}

			/// HHH-2378
			final Object realOldVersion = persister.isVersioned() ? oldVersion : null;
			
			boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(
					entity,
					realOldVersion,
					persister.getVersion( entity, source.getEntityMode() ),
					persister.getVersionType()
			);

			if ( canReplicate ) {
				//will result in a SQL UPDATE:
				performReplication( entity, id, realOldVersion, persister, replicationMode, source );
			}
			else {
				//else do nothing (don't even reassociate object!)
				log.trace( "no need to replicate" );
			}

			//TODO: would it be better to do a refresh from db?
		}
		else {
			// no existing row - do an insert
			if ( log.isTraceEnabled() ) {
				log.trace(
						"no existing row, replicating new instance " +
								MessageHelper.infoString( persister, id, source.getFactory() )
				);
			}

			final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
			final EntityKey key = regenerate ?
					null : new EntityKey( id, persister, source.getEntityMode() );

			performSaveOrReplicate(
					entity,
					key,
					persister,
					regenerate,
					replicationMode,
					source,
					true
			);

		}
	
private voidperformReplication(java.lang.Object entity, java.io.Serializable id, java.lang.Object version, org.hibernate.persister.entity.EntityPersister persister, org.hibernate.ReplicationMode replicationMode, org.hibernate.event.EventSource source)


		if ( log.isTraceEnabled() ) {
			log.trace(
					"replicating changes to " +
							MessageHelper.infoString( persister, id, source.getFactory() )
			);
		}

		new OnReplicateVisitor( source, id, entity, true ).process( entity, persister );

		source.getPersistenceContext().addEntity(
				entity,
				Status.MANAGED,
				null,
				new EntityKey( id, persister, source.getEntityMode() ),
				version,
				LockMode.NONE,
				true,
				persister,
				true,
				false
		);

		cascadeAfterReplicate( entity, persister, replicationMode, source );
	
protected booleansubstituteValuesIfNecessary(java.lang.Object entity, java.io.Serializable id, java.lang.Object[] values, org.hibernate.persister.entity.EntityPersister persister, org.hibernate.engine.SessionImplementor source)

		return false;
	
protected booleanvisitCollectionsBeforeSave(java.lang.Object entity, java.io.Serializable id, java.lang.Object[] values, org.hibernate.type.Type[] types, org.hibernate.event.EventSource source)

		//TODO: we use two visitors here, inefficient!
		OnReplicateVisitor visitor = new OnReplicateVisitor( source, id, entity, false );
		visitor.processEntityPropertyValues( values, types );
		return super.visitCollectionsBeforeSave( entity, id, values, types, source );