make generated id available in @PrePersist callbacks

This commit is contained in:
Gavin King 2023-08-22 22:33:49 +02:00
parent 0fdcdc2b7f
commit b67bb7403e
2 changed files with 37 additions and 19 deletions

View File

@ -25,6 +25,7 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.id.Assigned;
import org.hibernate.id.IdentifierGenerationException; import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -111,31 +112,34 @@ public abstract class AbstractSaveEventListener<C>
C context, C context,
EventSource source, EventSource source,
boolean requiresImmediateIdAccess) { boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
final EntityPersister persister = source.getEntityPersister( entityName, entity ); final EntityPersister persister = source.getEntityPersister( entityName, entity );
final Generator generator = persister.getGenerator(); final Generator generator = persister.getGenerator();
if ( !generator.generatedOnExecution() ) { if ( !generator.generatedOnExecution() ) {
final Object generatedId = ( (BeforeExecutionGenerator) generator ).generate( source, entity, null, INSERT ); final BeforeExecutionGenerator beforeExecutionGenerator = (BeforeExecutionGenerator) generator;
if ( generatedId == null ) { final Object generatedId;
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() ); if ( generator instanceof Assigned ) {
} // get it from the entity later, since we need
else if ( generatedId == SHORT_CIRCUIT_INDICATOR ) { // the preCreate() callback to happen first
return source.getIdentifier( entity ); generatedId = null;
} }
else { else {
// TODO: define toString()s for generators generatedId = beforeExecutionGenerator.generate( source, entity, null, INSERT );
if ( LOG.isDebugEnabled() ) { if ( generatedId == null ) {
LOG.debugf( throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
"Generated identifier: %s, using strategy: %s", }
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ), else if ( generatedId == SHORT_CIRCUIT_INDICATOR ) {
generator.getClass().getName() return source.getIdentifier( entity );
);
} }
return performSave( entity, generatedId, persister, false, context, source, true );
} }
// TODO: define toString()s for generators
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
generator.getClass().getName()
);
}
return performSave( entity, generatedId, persister, false, context, source, true );
} }
else { else {
return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess ); return performSave( entity, null, persister, true, context, source, requiresImmediateIdAccess );
@ -169,6 +173,20 @@ public abstract class AbstractSaveEventListener<C>
EventSource source, EventSource source,
boolean requiresImmediateIdAccess) { boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate( entity );
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
if ( persister.getGenerator() instanceof Assigned ) {
id = persister.getIdentifier( entity, source );
if ( id == null ) {
throw new IdentifierGenerationException(
"Identifier of entity '" + persister.getEntityName()
+ "' must be manually assigned before calling 'persist()'"
);
}
}
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Saving {0}", infoString( persister, id, source.getFactory() ) ); LOG.tracev( "Saving {0}", infoString( persister, id, source.getFactory() ) );
} }

View File

@ -36,7 +36,7 @@ public interface CallbackRegistry {
/** /**
* Signals that the CallbackRegistry will no longer be used. * Signals that the CallbackRegistry will no longer be used.
* In particular it is important to release references to class types * In particular, it is important to release references to class types
* to avoid classloader leaks. * to avoid classloader leaks.
*/ */
void release(); void release();