Skip to content

Commit

Permalink
Upgrade Hibernate ORM to 7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
DavideD committed Nov 18, 2024
1 parent 7eda8a9 commit bd5fd6f
Show file tree
Hide file tree
Showing 83 changed files with 1,086 additions and 1,188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import java.util.NoSuchElementException;
import java.util.function.Function;

import org.hibernate.engine.jdbc.BlobProxy;
import org.hibernate.engine.jdbc.ClobProxy;
import org.hibernate.engine.jdbc.proxy.BlobProxy;
import org.hibernate.engine.jdbc.proxy.ClobProxy;
import org.hibernate.type.descriptor.jdbc.JdbcType;

import io.vertx.core.buffer.Buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import org.hibernate.boot.spi.AbstractDelegatingMetadata;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedObjectRepository;
import org.hibernate.reactive.query.internal.ReactiveNamedObjectRepositoryImpl;

Expand All @@ -18,7 +17,7 @@ public ReactiveMetadataImplementor(MetadataImplementor delegate) {
}

@Override
public NamedObjectRepository buildNamedQueryRepository(SessionFactoryImplementor sessionFactory) {
return new ReactiveNamedObjectRepositoryImpl( delegate().buildNamedQueryRepository( sessionFactory ) );
public NamedObjectRepository buildNamedQueryRepository() {
return new ReactiveNamedObjectRepositoryImpl( super.buildNamedQueryRepository() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.PropertyValueException;
import org.hibernate.TransientObjectException;
import org.hibernate.action.internal.AbstractEntityInsertAction;
import org.hibernate.action.internal.BulkOperationCleanupAction;
import org.hibernate.action.internal.EntityDeleteAction;
import org.hibernate.action.internal.UnresolvedEntityInsertActions;
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
import org.hibernate.action.spi.Executable;
import org.hibernate.cache.CacheException;
import org.hibernate.engine.internal.NonNullableTransientDependencies;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.ComparableExecutable;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ExecutableList;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
Expand All @@ -59,7 +61,6 @@

import static java.lang.invoke.MethodHandles.lookup;
import static org.hibernate.reactive.logging.impl.LoggerFactory.make;
import static org.hibernate.reactive.util.impl.CompletionStages.failedFuture;
import static org.hibernate.reactive.util.impl.CompletionStages.loop;
import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture;

Expand Down Expand Up @@ -520,11 +521,21 @@ public CompletionStage<Void> executeInserts() {
*/
public CompletionStage<Void> executeActions() {
if ( hasUnresolvedEntityInsertActions() ) {
return failedFuture( new IllegalStateException( "About to execute actions, but there are unresolved entity insert actions." ) );
final AbstractEntityInsertAction insertAction = unresolvedInsertions
.getDependentEntityInsertActions()
.iterator()
.next();
final NonNullableTransientDependencies transientEntities = insertAction.findNonNullableTransientEntities();
final Object transientEntity = transientEntities.getNonNullableTransientEntities().iterator().next();
final String path = transientEntities.getNonNullableTransientPropertyPaths(transientEntity).iterator().next();
//TODO: should be TransientPropertyValueException
throw new TransientObjectException( "Persistent instance of '" + insertAction.getEntityName()
+ "' with id '" + insertAction.getId()
+ "' references an unsaved transient instance via attribute '" + path
+ "' (save the transient instance before flushing)" );
}

CompletionStage<Void> ret = voidFuture();

for ( OrderedActions action : ORDERED_OPERATIONS ) {
ret = ret.thenCompose( v -> executeActions( action.getActions( this ) ) );
}
Expand Down Expand Up @@ -738,26 +749,6 @@ public int numberOfInsertions() {
return insertions.size();
}

// public TransactionCompletionProcesses getTransactionCompletionProcesses() {
// return new TransactionCompletionProcesses( beforeTransactionProcesses(), afterTransactionProcesses() );
// }
//
// /**
// * Bind transaction completion processes to make them shared between primary and secondary session.
// * Transaction completion processes are always executed by transaction owner (primary session),
// * but can be registered using secondary session too.
// *
// * @param processes Transaction completion processes.
// * @param isTransactionCoordinatorShared Flag indicating shared transaction context.
// */
// public void setTransactionCompletionProcesses(
// TransactionCompletionProcesses processes,
// boolean isTransactionCoordinatorShared) {
// this.isTransactionCoordinatorShared = isTransactionCoordinatorShared;
// this.beforeTransactionProcesses = processes.beforeTransactionCompletionProcesses;
// this.afterTransactionProcesses = processes.afterTransactionCompletionProcesses;
// }

public void sortCollectionActions() {
if ( isOrderUpdatesEnabled() ) {
// sort the updates by fk
Expand Down Expand Up @@ -864,32 +855,6 @@ public void unScheduleDeletion(EntityEntry entry, Object rescuedEntity) {
throw new AssertionFailure( "Unable to perform un-delete for instance " + entry.getEntityName() );
}

// /**
// * Used by the owning session to explicitly control serialization of the action queue
// *
// * @param oos The stream to which the action queue should get written
// *
// * @throws IOException Indicates an error writing to the stream
// */
// public void serialize(ObjectOutputStream oos) throws IOException {
// LOG.trace( "Serializing action-queue" );
// if ( unresolvedInsertions == null ) {
// unresolvedInsertions = new UnresolvedEntityInsertActions();
// }
// unresolvedInsertions.serialize( oos );
//
// for ( ListProvider<?> p : EXECUTABLE_LISTS_MAP.values() ) {
// ExecutableList<?> l = p.get( this );
// if ( l == null ) {
// oos.writeBoolean( false );
// }
// else {
// oos.writeBoolean( true );
// l.writeExternal( oos );
// }
// }
// }

private abstract static class AbstractTransactionCompletionProcessQueue<T,U> {
final ReactiveSession session;

Expand Down Expand Up @@ -994,21 +959,6 @@ public CompletionStage<Void> afterTransactionCompletion(boolean success) {
}
}

// /**
// * Wrapper class allowing to bind the same transaction completion process queues in different sessions.
// */
// public static class TransactionCompletionProcesses {
// private final BeforeTransactionCompletionProcessQueue beforeTransactionCompletionProcesses;
// private final AfterTransactionCompletionProcessQueue afterTransactionCompletionProcesses;
//
// private TransactionCompletionProcesses(
// BeforeTransactionCompletionProcessQueue beforeTransactionCompletionProcessQueue,
// AfterTransactionCompletionProcessQueue afterTransactionCompletionProcessQueue) {
// this.beforeTransactionCompletionProcesses = beforeTransactionCompletionProcessQueue;
// this.afterTransactionCompletionProcesses = afterTransactionCompletionProcessQueue;
// }
// }

/**
* Order the {@link #insertions} queue such that we group inserts against the same entity together (without
* violating constraints). The original order is generated by cascade order, which in turn is based on the
Expand Down Expand Up @@ -1152,26 +1102,23 @@ public void sort(List<ReactiveEntityInsertActionHolder> insertions) {
*/
private void addParentChildEntityNames(ReactiveEntityInsertAction action, BatchIdentifier batchIdentifier) {
Object[] propertyValues = action.getState();
ClassMetadata classMetadata = action.getPersister().getClassMetadata();
if ( classMetadata != null ) {
Type[] propertyTypes = classMetadata.getPropertyTypes();
Type identifierType = classMetadata.getIdentifierType();

for ( int i = 0; i < propertyValues.length; i++ ) {
Object value = propertyValues[i];
if (value!=null) {
Type type = propertyTypes[i];
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, value );
}
Type[] propertyTypes = action.getPersister().getPropertyTypes();
Type identifierType = action.getPersister().getIdentifierType();

for ( int i = 0; i < propertyValues.length; i++ ) {
Object value = propertyValues[i];
if (value!=null) {
Type type = propertyTypes[i];
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, value );
}
}

if ( identifierType.isComponentType() ) {
CompositeType compositeType = (CompositeType) identifierType;
Type[] compositeIdentifierTypes = compositeType.getSubtypes();
if ( identifierType.isComponentType() ) {
CompositeType compositeType = (CompositeType) identifierType;
Type[] compositeIdentifierTypes = compositeType.getSubtypes();

for ( Type type : compositeIdentifierTypes ) {
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, null );
}
for ( Type type : compositeIdentifierTypes ) {
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, null );
}
}
}
Expand Down Expand Up @@ -1275,10 +1222,9 @@ public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( !( o instanceof BatchIdentifier ) ) {
if ( !( o instanceof BatchIdentifier that ) ) {
return false;
}
BatchIdentifier that = (BatchIdentifier) o;
return Objects.equals( entityName, that.entityName );
}

Expand Down Expand Up @@ -1315,9 +1261,7 @@ boolean hasAnyChildEntityNames(BatchIdentifier batchIdentifier) {
/**
* Check if this {@link BatchIdentifier} has a parent or grandparent
* matching the given {@link BatchIdentifier reference.
*
* @param batchIdentifier {@link BatchIdentifier} reference
*
* @return this {@link BatchIdentifier} has a parent matching the given {@link BatchIdentifier reference
*/
boolean hasParent(BatchIdentifier batchIdentifier) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.sql.SQLException;
import java.util.concurrent.CompletionStage;

import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
import org.hibernate.engine.jdbc.mutation.OperationResultChecker;
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
Expand Down Expand Up @@ -99,7 +100,8 @@ protected void performSelfExecutingOperations(
@Override
protected void performBatchedOperations(
ValuesAnalysis valuesAnalysis,
TableInclusionChecker inclusionChecker) {
TableInclusionChecker inclusionChecker,
Batch.StaleStateMapper staleStateMapper) {
throw LOG.nonReactiveMethodCall( "performReactiveBatchedOperations" );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import org.hibernate.event.spi.EventSource;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.Generator;
import org.hibernate.id.Assigned;
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
Expand Down Expand Up @@ -134,7 +134,7 @@ protected CompletionStage<Void> reactiveSaveWithGeneratedId(
// and is not yet available
generatedId = null;
}
else if ( generator instanceof Assigned ) {
else if ( !generator.generatesOnInsert() ) {
// get it from the entity later, since we need
// the @PrePersist callback to happen first
generatedId = null;
Expand All @@ -144,55 +144,58 @@ else if ( generator instanceof Assigned ) {
// the entity instance, so it will be available
// to the entity in the @PrePersist callback
if ( generator instanceof ReactiveIdentifierGenerator ) {
return ( (ReactiveIdentifierGenerator<?>) generator )
.generate( ( ReactiveConnectionSupplier ) source, entity )
.thenApply( id -> castToIdentifierType( id, persister ) )
.thenCompose( gid -> performSaveWithId(
entity,
context,
source,
persister,
generator,
gid,
requiresImmediateIdAccess,
false
) );
return generateId( entity, source, (ReactiveIdentifierGenerator<?>) generator, persister )
.thenCompose( gid -> {
if ( gid == SHORT_CIRCUIT_INDICATOR ) {
source.getIdentifier( entity );
return voidFuture();
}
persister.setIdentifier( entity, gid, source );
return reactivePerformSave(
entity,
gid,
persister,
generatedOnExecution,
context,
source,
false
);
} );
}

generatedId = ( (BeforeExecutionGenerator) generator ).generate( source, entity, null, INSERT );
if ( generatedId == SHORT_CIRCUIT_INDICATOR ) {
source.getIdentifier( entity );
return voidFuture();
}
persister.setIdentifier( entity, generatedId, source );
}
final Object id = castToIdentifierType( generatedId, persister );
return reactivePerformSave( entity, id, persister, generatedOnExecution, context, source, requiresImmediateIdAccess );
final boolean delayIdentityInserts = !source.isTransactionInProgress() && !requiresImmediateIdAccess && generatedOnExecution;
return reactivePerformSave( entity, id, persister, generatedOnExecution, context, source, delayIdentityInserts );
}

private CompletionStage<Void> performSaveWithId(
private CompletionStage<Object> generateId(
Object entity,
C context,
EventSource source,
EntityPersister persister,
Generator generator,
Object generatedId,
boolean requiresImmediateIdAccess,
boolean generatedOnExecution) {
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for: " + entity.getClass() );
}
if ( generatedId == SHORT_CIRCUIT_INDICATOR ) {
source.getIdentifier( entity );
return voidFuture();
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
generator.getClass().getName()
);
}
final boolean delayIdentityInserts =
!source.isTransactionInProgress()
&& !requiresImmediateIdAccess
&& generatedOnExecution;
return reactivePerformSave( entity, generatedId, persister, false, context, source, delayIdentityInserts );
ReactiveIdentifierGenerator<?> generator,
EntityPersister persister) {
return generator
.generate( (ReactiveConnectionSupplier) source, entity )
.thenApply( id -> castToIdentifierType( id, persister ) )
.thenCompose( generatedId -> {
if ( generatedId == null ) {
return failedFuture( new IdentifierGenerationException( "null id generated for: " + entity.getClass() ) );
}
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Generated identifier: %s, using strategy: %s",
persister.getIdentifierType().toLoggableString( generatedId, source.getFactory() ),
generator.getClass().getName()
);
}
return completedFuture( generatedId );
} );
}

/**
Expand Down Expand Up @@ -229,13 +232,11 @@ protected CompletionStage<Void> reactivePerformSave(
processIfSelfDirtinessTracker( entity, SelfDirtinessTracker::$$_hibernate_clearDirtyAttributes );
processIfManagedEntity( entity, managedEntity -> managedEntity.$$_hibernate_setUseTracker( true ) );

if ( persister.getGenerator() instanceof Assigned ) {
final Generator generator = persister.getGenerator();
if ( !generator.generatesOnInsert() || generator instanceof CompositeNestedGeneratedValueGenerator ) {
id = persister.getIdentifier( entity, source );
if ( id == null ) {
throw new IdentifierGenerationException(
"Identifier of entity '" + persister.getEntityName()
+ "' must be manually assigned before calling 'persist()'"
);
return failedFuture( new IdentifierGenerationException( "Identifier of entity '" + persister.getEntityName() + "' must be manually assigned before calling 'persist()'" ) );
}
}

Expand Down Expand Up @@ -420,7 +421,7 @@ private CompletionStage<AbstractEntityInsertAction> addInsertAction(
boolean useIdentityColumn,
EventSource source,
boolean shouldDelayIdentityInserts) {
final ReactiveActionQueue actionQueue = source.unwrap( ReactiveSession.class ).getReactiveActionQueue();
final ReactiveActionQueue actionQueue = source.unwrap(ReactiveSession.class).getReactiveActionQueue();
if ( useIdentityColumn ) {
final ReactiveEntityIdentityInsertAction insert = new ReactiveEntityIdentityInsertAction(
values, entity, persister, false, source, shouldDelayIdentityInserts
Expand Down
Loading

0 comments on commit bd5fd6f

Please sign in to comment.