HHH-17122 clean up old code in save event listeners, and finish id from @PrePersist
This commit is contained in:
parent
bead7dec50
commit
0b4cc3cc7e
|
@ -78,17 +78,8 @@ public abstract class AbstractSaveEventListener<C>
|
|||
String entityName,
|
||||
C context,
|
||||
EventSource source) {
|
||||
callbackRegistry.preCreate( entity );
|
||||
|
||||
return performSave(
|
||||
entity,
|
||||
requestedId,
|
||||
source.getEntityPersister( entityName, entity ),
|
||||
false,
|
||||
context,
|
||||
source,
|
||||
true
|
||||
);
|
||||
final EntityPersister persister = source.getEntityPersister( entityName, entity );
|
||||
return performSave( entity, requestedId, persister, false, context, source, false );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,9 +90,9 @@ public abstract class AbstractSaveEventListener<C>
|
|||
* @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).
|
||||
* 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
|
||||
|
@ -114,35 +105,65 @@ public abstract class AbstractSaveEventListener<C>
|
|||
boolean requiresImmediateIdAccess) {
|
||||
final EntityPersister persister = source.getEntityPersister( entityName, entity );
|
||||
final Generator generator = persister.getGenerator();
|
||||
if ( !generator.generatedOnExecution() ) {
|
||||
final BeforeExecutionGenerator beforeExecutionGenerator = (BeforeExecutionGenerator) generator;
|
||||
final Object generatedId;
|
||||
if ( generator instanceof Assigned ) {
|
||||
// get it from the entity later, since we need
|
||||
// the preCreate() callback to happen first
|
||||
generatedId = null;
|
||||
final boolean generatedOnExecution = generator.generatedOnExecution();
|
||||
final Object generatedId;
|
||||
if ( generatedOnExecution ) {
|
||||
// the id gets generated by the database
|
||||
// and is not yet available
|
||||
generatedId = null;
|
||||
}
|
||||
else if ( generator instanceof Assigned ) {
|
||||
// get it from the entity later, since we need
|
||||
// the @PrePersist callback to happen first
|
||||
generatedId = null;
|
||||
}
|
||||
else {
|
||||
// go ahead and generate id, and then set it to
|
||||
// the entity instance, so it will be available
|
||||
// to the entity in the @PrePersist callback
|
||||
generatedId = generateId( entity, source, (BeforeExecutionGenerator) generator, persister );
|
||||
if ( generatedId == SHORT_CIRCUIT_INDICATOR ) {
|
||||
return source.getIdentifier( entity );
|
||||
}
|
||||
else {
|
||||
generatedId = beforeExecutionGenerator.generate( source, entity, null, INSERT );
|
||||
if ( generatedId == null ) {
|
||||
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
|
||||
}
|
||||
else if ( generatedId == SHORT_CIRCUIT_INDICATOR ) {
|
||||
return source.getIdentifier( entity );
|
||||
}
|
||||
}
|
||||
// TODO: define toString()s for generators
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
persister.setIdentifier( entity, generatedId, source );
|
||||
}
|
||||
final boolean delayIdentityInserts =
|
||||
!source.isTransactionInProgress()
|
||||
&& !requiresImmediateIdAccess
|
||||
&& generatedOnExecution;
|
||||
return performSave( entity, generatedId, persister, generatedOnExecution, context, source, delayIdentityInserts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an id before execution of the insert statements,
|
||||
* using the given {@link BeforeExecutionGenerator}.
|
||||
*
|
||||
* @param entity The entity instance to be saved
|
||||
* @param source The session which is the source of this save event.
|
||||
* @param generator The entity's generator
|
||||
* @param persister The entity's persister instance.
|
||||
*
|
||||
* @return The generated id
|
||||
*/
|
||||
private static Object generateId(
|
||||
Object entity,
|
||||
EventSource source,
|
||||
BeforeExecutionGenerator generator,
|
||||
EntityPersister persister) {
|
||||
final Object id = generator.generate( source, entity, null, INSERT );
|
||||
if ( id == null ) {
|
||||
throw new IdentifierGenerationException( "Null id generated for entity '" + persister.getEntityName() + "'" );
|
||||
}
|
||||
else {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
// TODO: define toString()s for generators
|
||||
LOG.debugf(
|
||||
"Generated identifier: %s, using strategy: %s",
|
||||
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
|
||||
persister.getIdentifierType().toLoggableString( id, source.getFactory() ),
|
||||
generator.getClass().getName()
|
||||
);
|
||||
}
|
||||
return performSave( entity, generatedId, persister, false, context, source, true );
|
||||
}
|
||||
else {
|
||||
return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess );
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,13 +177,10 @@ public abstract class AbstractSaveEventListener<C>
|
|||
* @param useIdentityColumn Is an identity column being used?
|
||||
* @param context Generally cascade-specific information.
|
||||
* @param source The session from which the event originated.
|
||||
* @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).
|
||||
* @param delayIdentityInserts Should the identity insert be delayed?
|
||||
*
|
||||
* @return The id used to save the entity; may be null depending on the
|
||||
* type of id generator used and the requiresImmediateIdAccess value
|
||||
* type of id generator used and on delayIdentityInserts
|
||||
*/
|
||||
protected Object performSave(
|
||||
Object entity,
|
||||
|
@ -171,8 +189,10 @@ public abstract class AbstractSaveEventListener<C>
|
|||
boolean useIdentityColumn,
|
||||
C context,
|
||||
EventSource source,
|
||||
boolean requiresImmediateIdAccess) {
|
||||
boolean delayIdentityInserts) {
|
||||
|
||||
// call this after generation of an id,
|
||||
// but before we retrieve an assigned id
|
||||
callbackRegistry.preCreate( entity );
|
||||
|
||||
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
|
||||
|
@ -191,45 +211,31 @@ public abstract class AbstractSaveEventListener<C>
|
|||
LOG.tracev( "Saving {0}", infoString( persister, id, source.getFactory() ) );
|
||||
}
|
||||
|
||||
final EntityKey key = entityKey( entity, id, persister, useIdentityColumn, source );
|
||||
final EntityKey key = useIdentityColumn ? null : entityKey( id, persister, source );
|
||||
if ( invokeSaveLifecycle( entity, persister, source ) ) {
|
||||
return id;
|
||||
}
|
||||
else {
|
||||
return performSaveOrReplicate(
|
||||
entity,
|
||||
key,
|
||||
persister,
|
||||
useIdentityColumn,
|
||||
context,
|
||||
source,
|
||||
requiresImmediateIdAccess
|
||||
);
|
||||
return performSaveOrReplicate( entity, key, persister, useIdentityColumn, context, source, delayIdentityInserts );
|
||||
}
|
||||
}
|
||||
|
||||
private static EntityKey entityKey(Object entity, Object id, EntityPersister persister, boolean useIdentityColumn, EventSource source) {
|
||||
if ( !useIdentityColumn ) {
|
||||
final EntityKey key = source.generateEntityKey( id, persister );
|
||||
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
||||
final Object old = persistenceContext.getEntity( key );
|
||||
if ( old != null ) {
|
||||
if ( persistenceContext.getEntry( old ).getStatus() == Status.DELETED ) {
|
||||
source.forceFlush( persistenceContext.getEntry( old ) );
|
||||
}
|
||||
else {
|
||||
throw new NonUniqueObjectException( id, persister.getEntityName() );
|
||||
}
|
||||
private static EntityKey entityKey(Object id, EntityPersister persister, EventSource source) {
|
||||
final EntityKey key = source.generateEntityKey( id, persister );
|
||||
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
||||
final Object old = persistenceContext.getEntity( key );
|
||||
if ( old != null ) {
|
||||
if ( persistenceContext.getEntry( old ).getStatus() == Status.DELETED ) {
|
||||
source.forceFlush( persistenceContext.getEntry( old ) );
|
||||
}
|
||||
else if ( persistenceContext.containsDeletedUnloadedEntityKey( key ) ) {
|
||||
source.forceFlush( key );
|
||||
else {
|
||||
throw new NonUniqueObjectException( id, persister.getEntityName() );
|
||||
}
|
||||
persister.setIdentifier( entity, id, source );
|
||||
return key;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
else if ( persistenceContext.containsDeletedUnloadedEntityKey( key ) ) {
|
||||
source.forceFlush( key );
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) {
|
||||
|
@ -255,8 +261,7 @@ public abstract class AbstractSaveEventListener<C>
|
|||
* @param useIdentityColumn Should an identity column be used for id generation?
|
||||
* @param context Generally cascade-specific information.
|
||||
* @param source The session which is the source of the current event.
|
||||
* @param requiresImmediateIdAccess Is access to the identifier required immediately
|
||||
* after the completion of the save? persist(), for example, does not require this...
|
||||
* @param delayIdentityInserts Should the identity insert be delayed?
|
||||
*
|
||||
* @return The id used to save the entity; may be null depending on the
|
||||
* type of id generator used and the requiresImmediateIdAccess value
|
||||
|
@ -268,11 +273,10 @@ public abstract class AbstractSaveEventListener<C>
|
|||
boolean useIdentityColumn,
|
||||
C context,
|
||||
EventSource source,
|
||||
boolean requiresImmediateIdAccess) {
|
||||
boolean delayIdentityInserts) {
|
||||
|
||||
final Object id = key == null ? null : key.getIdentifier();
|
||||
|
||||
final boolean shouldDelayIdentityInserts = !source.isTransactionInProgress() && !requiresImmediateIdAccess;
|
||||
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
||||
|
||||
// Put a placeholder in entries, so we don't recurse back and try to save() the
|
||||
|
@ -300,7 +304,7 @@ public abstract class AbstractSaveEventListener<C>
|
|||
persister,
|
||||
useIdentityColumn,
|
||||
source,
|
||||
shouldDelayIdentityInserts
|
||||
delayIdentityInserts
|
||||
);
|
||||
|
||||
// postpone initializing id in case the insert has non-nullable transient dependencies
|
||||
|
@ -369,7 +373,7 @@ public abstract class AbstractSaveEventListener<C>
|
|||
EntityPersister persister,
|
||||
boolean useIdentityColumn,
|
||||
EventSource source,
|
||||
boolean shouldDelayIdentityInserts) {
|
||||
boolean delayIdentityInserts) {
|
||||
if ( useIdentityColumn ) {
|
||||
final EntityIdentityInsertAction insert = new EntityIdentityInsertAction(
|
||||
values,
|
||||
|
@ -377,7 +381,7 @@ public abstract class AbstractSaveEventListener<C>
|
|||
persister,
|
||||
isVersionIncrementDisabled(),
|
||||
source,
|
||||
shouldDelayIdentityInserts
|
||||
delayIdentityInserts
|
||||
);
|
||||
source.getActionQueue().addAction( insert );
|
||||
return insert;
|
||||
|
|
|
@ -126,16 +126,7 @@ public class DefaultReplicateEventListener
|
|||
final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
|
||||
final EntityKey key = regenerate ? null : source.generateEntityKey( id, persister );
|
||||
|
||||
performSaveOrReplicate(
|
||||
entity,
|
||||
key,
|
||||
persister,
|
||||
regenerate,
|
||||
replicationMode,
|
||||
source,
|
||||
true
|
||||
);
|
||||
|
||||
performSaveOrReplicate( entity, key, persister, regenerate, replicationMode, source, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,29 +26,14 @@ public class DefaultSaveEventListener extends DefaultSaveOrUpdateEventListener {
|
|||
protected Object performSaveOrUpdate(SaveOrUpdateEvent event) {
|
||||
// this implementation is supposed to tolerate incorrect unsaved-value
|
||||
// mappings, for the purpose of backward-compatibility
|
||||
EntityEntry entry = event.getSession().getPersistenceContextInternal().getEntry( event.getEntity() );
|
||||
final EntityEntry entry = event.getSession().getPersistenceContextInternal().getEntry( event.getEntity() );
|
||||
return entry != null && entry.getStatus() != Status.DELETED
|
||||
? entityIsPersistent( event )
|
||||
: entityIsTransient( event );
|
||||
}
|
||||
|
||||
protected Object saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) {
|
||||
if ( event.getRequestedId() == null ) {
|
||||
return super.saveWithGeneratedOrRequestedId( event );
|
||||
}
|
||||
else {
|
||||
return saveWithRequestedId(
|
||||
event.getEntity(),
|
||||
event.getRequestedId(),
|
||||
event.getEntityName(),
|
||||
null,
|
||||
event.getSession()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean reassociateIfUninitializedProxy(Object object, SessionImplementor source) {
|
||||
if ( !Hibernate.isInitialized(object) ) {
|
||||
if ( !Hibernate.isInitialized( object ) ) {
|
||||
throw new PersistentObjectException("uninitialized proxy passed to save()");
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -11,7 +11,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.classic.Lifecycle;
|
||||
import org.hibernate.engine.internal.Cascade;
|
||||
import org.hibernate.engine.internal.CascadePoint;
|
||||
|
@ -88,7 +87,7 @@ public class DefaultSaveOrUpdateEventListener
|
|||
}
|
||||
|
||||
protected Object performSaveOrUpdate(SaveOrUpdateEvent event) {
|
||||
EntityState entityState = EntityState.getEntityState(
|
||||
final EntityState entityState = EntityState.getEntityState(
|
||||
event.getEntity(),
|
||||
event.getEntityName(),
|
||||
event.getEntry(),
|
||||
|
@ -123,26 +122,21 @@ public class DefaultSaveOrUpdateEventListener
|
|||
|
||||
final SessionFactoryImplementor factory = event.getSession().getFactory();
|
||||
|
||||
Object requestedId = event.getRequestedId();
|
||||
|
||||
Object savedId;
|
||||
final Object requestedId = event.getRequestedId();
|
||||
final Object savedId;
|
||||
if ( requestedId == null ) {
|
||||
savedId = entityEntry.getId();
|
||||
}
|
||||
else {
|
||||
|
||||
final boolean isEqual = entityEntry.getPersister().getIdentifierType()
|
||||
.isEqual( requestedId, entityEntry.getId(), factory );
|
||||
|
||||
if ( isEqual ) {
|
||||
throw new PersistentObjectException(
|
||||
"object passed to save() was already persistent: " +
|
||||
MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
|
||||
);
|
||||
}
|
||||
|
||||
savedId = requestedId;
|
||||
|
||||
}
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
|
@ -172,7 +166,7 @@ public class DefaultSaveOrUpdateEventListener
|
|||
|
||||
final EventSource source = event.getSession();
|
||||
|
||||
EntityEntry entityEntry = event.getEntry();
|
||||
final EntityEntry entityEntry = event.getEntry();
|
||||
if ( entityEntry != null ) {
|
||||
if ( entityEntry.getStatus() == Status.DELETED ) {
|
||||
source.forceFlush( entityEntry );
|
||||
|
@ -182,28 +176,20 @@ public class DefaultSaveOrUpdateEventListener
|
|||
}
|
||||
}
|
||||
|
||||
Object id = saveWithGeneratedOrRequestedId( event );
|
||||
|
||||
source.getPersistenceContextInternal().reassociateProxy( event.getObject(), id );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the transient instance, assigning the right identifier
|
||||
*
|
||||
* @param event The initiating event.
|
||||
*
|
||||
* @return The entity's identifier value after saving.
|
||||
*/
|
||||
protected Object saveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) {
|
||||
return saveWithGeneratedId(
|
||||
if ( event.getRequestedId() != null ) {
|
||||
throw new AssertionFailure( "requested id should be null in save" );
|
||||
}
|
||||
final Object id = saveWithGeneratedId(
|
||||
event.getEntity(),
|
||||
event.getEntityName(),
|
||||
null,
|
||||
event.getSession(),
|
||||
true
|
||||
);
|
||||
|
||||
source.getPersistenceContextInternal().reassociateProxy( event.getObject(), id );
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,8 +208,8 @@ public class DefaultSaveOrUpdateEventListener
|
|||
throw new AssertionFailure( "entity was persistent" );
|
||||
}
|
||||
|
||||
Object entity = event.getEntity();
|
||||
EntityPersister persister = session.getEntityPersister( event.getEntityName(), entity );
|
||||
final Object entity = event.getEntity();
|
||||
final EntityPersister persister = session.getEntityPersister( event.getEntityName(), entity );
|
||||
event.setRequestedId( getUpdateId( entity, persister, event.getRequestedId(), session ) );
|
||||
performUpdate( event, entity, persister );
|
||||
}
|
||||
|
@ -242,7 +228,7 @@ public class DefaultSaveOrUpdateEventListener
|
|||
*/
|
||||
protected Object getUpdateId(Object entity, EntityPersister persister, Object requestedId, SessionImplementor session) {
|
||||
// use the id assigned to the instance
|
||||
Object id = persister.getIdentifier( entity, session );
|
||||
final Object id = persister.getIdentifier( entity, session );
|
||||
if ( id == null ) {
|
||||
// assume this is a newly instantiated transient object
|
||||
// which should be saved rather than updated
|
||||
|
|
Loading…
Reference in New Issue