下面列出了org.hibernate.event.spi.EventSource#getEntityPersister ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private CompletionStage<Void> entityIsDeleted(PersistEvent event, IdentitySet createCache) {
final EventSource source = event.getSession();
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
"un-scheduling entity deletion [%s]",
MessageHelper.infoString(
persister,
persister.getIdentifier( entity, source ),
source.getFactory()
)
);
}
if ( createCache.add( entity ) ) {
return justCascade( createCache, source, entity, persister );
}
return CompletionStages.nullFuture();
}
@SuppressWarnings({"unchecked"})
private void entityIsDeleted(PersistEvent event, Map createCache) {
final EventSource source = event.getSession();
final Object entity = source.getPersistenceContext().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
LOG.tracef(
"un-scheduling entity deletion [%s]",
MessageHelper.infoString(
persister,
persister.getIdentifier( entity, source ),
source.getFactory()
)
);
if ( createCache.put( entity, entity ) == null ) {
justCascade( createCache, source, entity, persister );
}
}
protected CompletionStage<Void> entityIsPersistent(PersistEvent event, IdentitySet createCache) {
LOG.trace( "Ignoring persistent instance" );
final EventSource source = event.getSession();
//TODO: check that entry.getIdentifier().equals(requestedId)
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( createCache.add( entity ) ) {
return justCascade( createCache, source, entity, persister );
}
return CompletionStages.nullFuture();
}
private void disallowDeletionOfDetached(DeleteEvent event) {
EventSource source = event.getSession();
String entityName = event.getEntityName();
EntityPersister persister = source.getEntityPersister( entityName, event.getObject() );
Serializable id = persister.getIdentifier( event.getObject(), source );
entityName = entityName == null ? source.guessEntityName( event.getObject() ) : entityName;
throw new IllegalArgumentException( "Removing a detached instance " + entityName + "#" + id );
}
private static Serializable assignIdIfNecessary(Object generatedId, Object entity, String entityName, EventSource source) {
EntityPersister persister = source.getEntityPersister(entityName, entity);
if ( generatedId != null ) {
if (generatedId instanceof Long) {
Long longId = (Long) generatedId;
Type identifierType = persister.getIdentifierType();
if (identifierType == LongType.INSTANCE) {
return longId;
}
else if (identifierType == IntegerType.INSTANCE) {
return longId.intValue();
}
else {
throw new HibernateException("cannot generate identifiers of type "
+ identifierType.getReturnedClass().getSimpleName() + " for: " + entityName);
}
}
else {
return (Serializable) generatedId;
}
}
else {
Serializable assignedId = persister.getIdentifier( entity, source.getSession() );
if (assignedId == null) {
throw new IdentifierGenerationException("ids for this class must be manually assigned before calling save(): " + entityName);
}
return assignedId;
}
}
/**
* Prepares the save call using a newly generated id.
*
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
* @param context Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
*
* @return The id used to save the entity; may be null depending on the
* type of id generator used and the requiresImmediateIdAccess value
*/
protected CompletionStage<Void> reactiveSaveWithGeneratedId(
Object entity,
String entityName,
C context,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
EntityPersister persister = source.getEntityPersister( entityName, entity );
boolean autoincrement = persister.isIdentifierAssignedByInsert();
return generateId( entity, source, persister )
.thenCompose(id ->
reactivePerformSave(
entity,
autoincrement ? null : assignIdIfNecessary( id, entity, entityName, source ),
persister,
autoincrement,
context,
source,
!autoincrement || requiresImmediateIdAccess
)
);
}
private void disallowDeletionOfDetached(DeleteEvent event) {
EventSource source = event.getSession();
String entityName = event.getEntityName();
EntityPersister persister = source.getEntityPersister( entityName, event.getObject() );
Serializable id = persister.getIdentifier( event.getObject(), source );
entityName = entityName == null ? source.guessEntityName( event.getObject() ) : entityName;
throw new IllegalArgumentException("Removing a detached instance "+ entityName + "#" + id);
}
@SuppressWarnings({"unchecked"})
protected void entityIsPersistent(PersistEvent event, Map createCache) {
LOG.trace( "Ignoring persistent instance" );
final EventSource source = event.getSession();
//TODO: check that entry.getIdentifier().equals(requestedId)
final Object entity = source.getPersistenceContext().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( createCache.put( entity, entity ) == null ) {
justCascade( createCache, source, entity, persister );
}
}
protected void entityIsTransient(MergeEvent event, Map copyCache) {
LOG.trace( "Merging transient instance" );
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final String entityName = event.getEntityName();
final EntityPersister persister = source.getEntityPersister( entityName, entity );
final Serializable id = persister.hasIdentifierProperty() ?
persister.getIdentifier( entity, source ) :
null;
if ( copyCache.containsKey( entity ) ) {
persister.setIdentifier( copyCache.get( entity ), id, source );
}
else {
( (MergeContext) copyCache ).put( entity, source.instantiate( persister, id ), true ); //before cascade!
}
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.FROM_PARENT );
saveTransientEntity( copy, entityName, event.getRequestedId(), source, copyCache );
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
super.cascadeAfterSave( source, persister, entity, copyCache );
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT );
event.setResult( copy );
}
/**
* Prepares the save call using a newly generated id.
*
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
* @param anything Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after execution of this method (if
* not, post-insert style id generators may be postponed if we are outside
* a transaction).
*
* @return The id used to save the entity; may be null depending on the
* type of id generator used and the requiresImmediateIdAccess value
*/
protected Serializable saveWithGeneratedId(
Object entity,
String entityName,
Object anything,
EventSource source,
boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
EntityPersister persister = source.getEntityPersister( entityName, entity );
Serializable generatedId = persister.getIdentifierGenerator().generate( source, entity );
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() );
}
else if ( generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR ) {
return source.getIdentifier( entity );
}
else if ( generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR ) {
return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess );
}
else {
// TODO: define toString()s for generators
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
persister.getIdentifierGenerator().getClass().getName()
);
}
return performSave( entity, generatedId, persister, false, anything, source, true );
}
}
/**
* Handle the given delete event. This is the cascaded form.
*
* @param event The delete event.
* @param transientEntities The cache of entities already deleted
*
* @throws HibernateException
*/
public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException {
final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContext();
Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
EntityEntry entityEntry = persistenceContext.getEntry( entity );
final EntityPersister persister;
final Serializable id;
final Object version;
if ( entityEntry == null ) {
LOG.trace( "Entity was not persistent in delete processing" );
persister = source.getEntityPersister( event.getEntityName(), entity );
if ( ForeignKeys.isTransient( persister.getEntityName(), entity, null, source ) ) {
deleteTransientEntity( source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities );
// EARLY EXIT!!!
return;
}
performDetachedEntityDeletionCheck( event );
id = persister.getIdentifier( entity, source );
if ( id == null ) {
throw new TransientObjectException(
"the detached instance passed to delete() had a null identifier"
);
}
final EntityKey key = source.generateEntityKey( id, persister );
persistenceContext.checkUniqueness( key, entity );
new OnUpdateVisitor( source, id, entity ).process( entity, persister );
version = persister.getVersion( entity );
entityEntry = persistenceContext.addEntity(
entity,
(persister.isMutable() ? Status.MANAGED : Status.READ_ONLY),
persister.getPropertyValues( entity ),
key,
version,
LockMode.NONE,
true,
persister,
false
);
}
else {
LOG.trace( "Deleting a persistent instance" );
if ( entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE ) {
LOG.trace( "Object was already deleted" );
return;
}
persister = entityEntry.getPersister();
id = entityEntry.getId();
version = entityEntry.getVersion();
}
/*if ( !persister.isMutable() ) {
throw new HibernateException(
"attempted to delete an object of immutable class: " +
MessageHelper.infoString(persister)
);
}*/
if ( invokeDeleteLifecycle( source, entity, persister ) ) {
return;
}
deleteEntity(
source,
entity,
entityEntry,
event.isCascadeDeleteEnabled(),
event.isOrphanRemovalBeforeUpdates(),
persister,
transientEntities
);
if ( source.getFactory().getSettings().isIdentifierRollbackEnabled() ) {
persister.resetIdentifier( entity, id, version, source );
}
}
/**
* Handle the given merge event.
*
* @param event The merge event to be handled.
*
* @throws HibernateException
*/
public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException {
final MergeContext copyCache = (MergeContext) copiedAlready;
final EventSource source = event.getSession();
final Object original = event.getOriginal();
if ( original != null ) {
final Object entity;
if ( original instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
LOG.trace( "Ignoring uninitialized proxy" );
event.setResult( source.load( li.getEntityName(), li.getIdentifier() ) );
return; //EARLY EXIT!
}
else {
entity = li.getImplementation();
}
}
else {
entity = original;
}
if ( copyCache.containsKey( entity ) &&
( copyCache.isOperatedOn( entity ) ) ) {
LOG.trace( "Already in merge process" );
event.setResult( entity );
}
else {
if ( copyCache.containsKey( entity ) ) {
LOG.trace( "Already in copyCache; setting in merge process" );
copyCache.setOperatedOn( entity, true );
}
event.setEntity( entity );
EntityState entityState = null;
// Check the persistence context for an entry relating to this
// entity to be merged...
EntityEntry entry = source.getPersistenceContext().getEntry( entity );
if ( entry == null ) {
EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
Serializable id = persister.getIdentifier( entity, source );
if ( id != null ) {
final EntityKey key = source.generateEntityKey( id, persister );
final Object managedEntity = source.getPersistenceContext().getEntity( key );
entry = source.getPersistenceContext().getEntry( managedEntity );
if ( entry != null ) {
// we have specialized case of a detached entity from the
// perspective of the merge operation. Specifically, we
// have an incoming entity instance which has a corresponding
// entry in the current persistence context, but registered
// under a different entity instance
entityState = EntityState.DETACHED;
}
}
}
if ( entityState == null ) {
entityState = getEntityState( entity, event.getEntityName(), entry, source );
}
switch ( entityState ) {
case DETACHED:
entityIsDetached( event, copyCache );
break;
case TRANSIENT:
entityIsTransient( event, copyCache );
break;
case PERSISTENT:
entityIsPersistent( event, copyCache );
break;
default: //DELETED
throw new ObjectDeletedException(
"deleted instance passed to merge",
null,
getLoggableName( event.getEntityName(), entity )
);
}
}
}
}
protected void entityIsPersistent(MergeEvent event, Map copyCache) {
LOG.trace( "Ignoring persistent instance" );
//TODO: check that entry.getIdentifier().equals(requestedId)
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
( (MergeContext) copyCache ).put( entity, entity, true ); //before cascade!
cascadeOnMerge( source, persister, entity, copyCache );
copyValues( persister, entity, entity, source, copyCache );
event.setResult( entity );
}
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.getLoadQueryInfluencers().getInternalFetchProfile();
source.getLoadQueryInfluencers().setInternalFetchProfile( "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.getLoadQueryInfluencers().setInternalFetchProfile( 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 {
( (MergeContext) 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().getStatistics().optimisticFailure( entityName );
}
throw new StaleObjectStateException( entityName, id );
}
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
cascadeOnMerge( source, persister, entity, copyCache );
copyValues( persister, entity, target, source, copyCache );
//copyValues works by reflection, so explicitly mark the entity instance dirty
markInterceptorDirty( entity, target, persister );
event.setResult( result );
}
}