diff --git a/README.md b/README.md index 01f3e17c0..aabf550ac 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Hibernate Reactive has been tested with: - CockroachDB v24 - MS SQL Server 2022 - Oracle 23 -- [Hibernate ORM][] 7.0.0.Beta3 +- [Hibernate ORM][] 7.0.0.Beta4 - [Vert.x Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/) 4.5.12 - [Vert.x Reactive MySQL Client](https://vertx.io/docs/vertx-mysql-client/java/) 4.5.12 - [Vert.x Reactive Db2 Client](https://vertx.io/docs/vertx-db2-client/java/) 4.5.12 diff --git a/gradle.properties b/gradle.properties index 911e9d9c4..b45735f0a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -35,12 +35,12 @@ org.gradle.java.installations.auto-download=false #enableMavenLocalRepo = true # The default Hibernate ORM version (override using `-PhibernateOrmVersion=the.version.you.want`) -hibernateOrmVersion = 7.0.0.Beta3 +hibernateOrmVersion = 7.0.0.Beta4 # Override default Hibernate ORM Gradle plugin version # Using the stable version because I don't know how to configure the build to download the snapshot version from # a remote repository -hibernateOrmGradlePluginVersion = 7.0.0.Beta2 +#hibernateOrmGradlePluginVersion = 7.0.0.Beta4 # If set to true, skip Hibernate ORM version parsing (default is true, if set to null) # this is required when using intervals or weird versions or the build will fail diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/engine/internal/ReactivePersistenceContextAdapter.java b/hibernate-reactive-core/src/main/java/org/hibernate/engine/internal/ReactivePersistenceContextAdapter.java new file mode 100644 index 000000000..92a678413 --- /dev/null +++ b/hibernate-reactive-core/src/main/java/org/hibernate/engine/internal/ReactivePersistenceContextAdapter.java @@ -0,0 +1,713 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.engine.internal; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.CompletionStage; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.hibernate.HibernateException; +import org.hibernate.Internal; +import org.hibernate.LockMode; +import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.engine.spi.BatchFetchQueue; +import org.hibernate.engine.spi.CollectionEntry; +import org.hibernate.engine.spi.CollectionKey; +import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.EntityHolder; +import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.EntityUniqueKey; +import org.hibernate.engine.spi.NaturalIdResolutions; +import org.hibernate.engine.spi.PersistenceContext; +import org.hibernate.engine.spi.PersistentAttributeInterceptable; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.engine.spi.Status; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.reactive.logging.impl.Log; +import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; +import org.hibernate.reactive.session.ReactiveSession; +import org.hibernate.sql.results.graph.entity.EntityInitializer; +import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; +import org.hibernate.sql.results.spi.LoadContexts; + +import static java.lang.invoke.MethodHandles.lookup; +import static org.hibernate.reactive.logging.impl.LoggerFactory.make; +import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; +import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; + +/** + * Add reactive methods to a {@link PersistenceContext}. + */ +public class ReactivePersistenceContextAdapter implements PersistenceContext { + + private static final Log LOG = make( Log.class, lookup() ); + + private final PersistenceContext delegate; + + /** + * Constructs a PersistentContext, bound to the given session. + */ + public ReactivePersistenceContextAdapter(PersistenceContext persistenceContext) { + this.delegate = persistenceContext; + } + + public CompletionStage reactiveInitializeNonLazyCollections() throws HibernateException { + final NonLazyCollectionInitializer initializer = new NonLazyCollectionInitializer(); + delegate.initializeNonLazyCollections( initializer ); + return initializer.stage; + } + + private class NonLazyCollectionInitializer implements Consumer> { + CompletionStage stage = voidFuture(); + + @Override + public void accept(PersistentCollection nonLazyCollection) { + if ( !nonLazyCollection.wasInitialized() ) { + stage = stage.thenCompose( v -> ( (ReactiveSession) getSession() ) + .reactiveInitializeCollection( nonLazyCollection, false ) ); + } + } + } + + /** + * @deprecated use {@link #reactiveInitializeNonLazyCollections} instead. + */ + @Deprecated + @Override + public void initializeNonLazyCollections() { + // still called by ResultSetProcessorImpl, so can't throw UnsupportedOperationException + } + + @Override + public void initializeNonLazyCollections(Consumer> initializeAction) { + throw LOG.nonReactiveMethodCall( "reactiveInitializeNonLazyCollection" ); + } + + @Deprecated + @Override + public Object[] getDatabaseSnapshot(Object id, EntityPersister persister) throws HibernateException { + throw LOG.nonReactiveMethodCall( "reactiveGetDatabaseSnapshot" ); + } + + private static final Object[] NO_ROW = new Object[] {StatefulPersistenceContext.NO_ROW}; + + public CompletionStage reactiveGetDatabaseSnapshot(Object id, EntityPersister persister) throws HibernateException { + SessionImplementor session = (SessionImplementor) getSession(); + final EntityKey key = session.generateEntityKey( id, persister ); + final Object[] cached = getEntitySnapshotsByKey() == null + ? null + : (Object[]) getEntitySnapshotsByKey().get( key ); + if ( cached != null ) { + return completedFuture( cached == NO_ROW ? null : cached ); + } + else { + return ( (ReactiveEntityPersister) persister ) + .reactiveGetDatabaseSnapshot( id, session ) + .thenApply( snapshot -> { + getOrInitializeEntitySnapshotsByKey().put( key, snapshot ); + return snapshot; + } ); + } + } + + @Override + public boolean isStateless() { + return delegate.isStateless(); + } + + @Override + public SharedSessionContractImplementor getSession() { + return delegate.getSession(); + } + + @Override + public LoadContexts getLoadContexts() { + return delegate.getLoadContexts(); + } + + @Override + public boolean hasLoadContext() { + return delegate.hasLoadContext(); + } + + @Override + public PersistentCollection useUnownedCollection(CollectionKey key) { + return delegate.useUnownedCollection( key ); + } + + @Override + public BatchFetchQueue getBatchFetchQueue() { + return delegate.getBatchFetchQueue(); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public void setEntryStatus(EntityEntry entry, Status status) { + delegate.setEntryStatus( entry, status ); + } + + @Override + public void afterTransactionCompletion() { + delegate.afterTransactionCompletion(); + } + + @Override + public Object[] getCachedDatabaseSnapshot(EntityKey key) { + return delegate.getCachedDatabaseSnapshot( key ); + } + + @Override + public Object getNaturalIdSnapshot(Object id, EntityPersister persister) { + return delegate.getNaturalIdSnapshot( id, persister ); + } + + @Override + public void addEntity(EntityKey key, Object entity) { + delegate.addEntity( key, entity ); + } + + @Override + public Object getEntity(EntityKey key) { + return delegate.getEntity( key ); + } + + @Override + public boolean containsEntity(EntityKey key) { + return delegate.containsEntity( key ); + } + + @Override + public Object removeEntity(EntityKey key) { + return delegate.removeEntity( key ); + } + + @Override + public void addEntity(EntityUniqueKey euk, Object entity) { + delegate.addEntity( euk, entity ); + } + + @Override + public Object getEntity(EntityUniqueKey euk) { + return delegate.getEntity( euk ); + } + + @Override + public EntityEntry getEntry(Object entity) { + return delegate.getEntry( entity ); + } + + @Override + public EntityEntry removeEntry(Object entity) { + return delegate.removeEntry( entity ); + } + + @Override + public boolean isEntryFor(Object entity) { + return delegate.isEntryFor( entity ); + } + + @Override + public CollectionEntry getCollectionEntry(PersistentCollection coll) { + return delegate.getCollectionEntry( coll ); + } + + @Override + public EntityEntry addEntity( + Object entity, + Status status, + Object[] loadedState, + EntityKey entityKey, + Object version, + LockMode lockMode, + boolean existsInDatabase, + EntityPersister persister, + boolean disableVersionIncrement) { + return delegate.addEntity( + entity, + status, + loadedState, + entityKey, + version, + lockMode, + existsInDatabase, + persister, + disableVersionIncrement + ); + } + + @Override + public EntityEntry addEntry( + Object entity, + Status status, + Object[] loadedState, + Object rowId, + Object id, + Object version, + LockMode lockMode, + boolean existsInDatabase, + EntityPersister persister, + boolean disableVersionIncrement) { + return delegate.addEntry( + entity, + status, + loadedState, + rowId, + id, + version, + lockMode, + existsInDatabase, + persister, + disableVersionIncrement + ); + } + + @Override + public EntityEntry addReferenceEntry(Object entity, Status status) { + return delegate.addReferenceEntry( entity, status ); + } + + @Override + public boolean containsCollection(PersistentCollection collection) { + return delegate.containsCollection( collection ); + } + + @Override + public boolean containsProxy(Object proxy) { + return delegate.containsProxy( proxy ); + } + + @Override + public boolean reassociateIfUninitializedProxy(Object value) { + return delegate.reassociateIfUninitializedProxy( value ); + } + + @Override + public void reassociateProxy(Object value, Object id) { + delegate.reassociateProxy( value, id ); + } + + @Override + public Object unproxy(Object maybeProxy) { + return delegate.unproxy( maybeProxy ); + } + + @Override + public Object unproxyAndReassociate(Object maybeProxy) { + return delegate.unproxyAndReassociate( maybeProxy ); + } + + @Override + public void checkUniqueness(EntityKey key, Object object) { + delegate.checkUniqueness( key, object ); + } + + @Override + public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key, Object object) { + return delegate.narrowProxy( proxy, persister, key, object ); + } + + @Override + public Object proxyFor(EntityPersister persister, EntityKey key, Object impl) { + return delegate.proxyFor( persister, key, impl ); + } + + @Override + public Object proxyFor(Object impl) { + return delegate.proxyFor( impl ); + } + + @Override + public Object proxyFor(EntityHolder holder, EntityPersister persister) { + return delegate.proxyFor( holder, persister ); + } + + @Override + public void addEnhancedProxy(EntityKey key, PersistentAttributeInterceptable entity) { + delegate.addEnhancedProxy( key, entity ); + } + + @Override + public Object getCollectionOwner(Object key, CollectionPersister collectionPersister) { + return delegate.getCollectionOwner( key, collectionPersister ); + } + + @Override + public Object getLoadedCollectionOwnerOrNull(PersistentCollection collection) { + return delegate.getLoadedCollectionOwnerOrNull( collection ); + } + + @Override + public Object getLoadedCollectionOwnerIdOrNull(PersistentCollection collection) { + return delegate.getLoadedCollectionOwnerIdOrNull( collection ); + } + + @Override + public void addUninitializedCollection(CollectionPersister persister, PersistentCollection collection, Object id) { + delegate.addUninitializedCollection( persister, collection, id ); + } + + @Override + public void addUninitializedDetachedCollection(CollectionPersister persister, PersistentCollection collection) { + delegate.addUninitializedDetachedCollection( persister, collection ); + } + + @Override + public void addNewCollection(CollectionPersister persister, PersistentCollection collection) { + delegate.addNewCollection( persister, collection ); + } + + @Override + public void addInitializedDetachedCollection(CollectionPersister collectionPersister, PersistentCollection collection) { + delegate.addInitializedDetachedCollection( collectionPersister, collection ); + } + + @Override + public void replaceCollection(CollectionPersister persister, PersistentCollection oldCollection, PersistentCollection collection) { + delegate.replaceCollection( persister, oldCollection, collection ); + } + + @Override + public CollectionEntry addInitializedCollection(CollectionPersister persister, PersistentCollection collection, Object id) { + return delegate.addInitializedCollection( persister, collection, id ); + } + + @Override + public PersistentCollection getCollection(CollectionKey collectionKey) { + return delegate.getCollection( collectionKey ); + } + + @Override + public void addNonLazyCollection(PersistentCollection collection) { + delegate.addNonLazyCollection( collection ); + } + + @Override + public PersistentCollection getCollectionHolder(Object array) { + return delegate.getCollectionHolder( array ); + } + + @Override + public void addCollectionHolder(PersistentCollection holder) { + delegate.addCollectionHolder( holder ); + } + + @Override + public PersistentCollection removeCollectionHolder(Object array) { + return delegate.removeCollectionHolder( array ); + } + + @Override + public Serializable getSnapshot(PersistentCollection coll) { + return delegate.getSnapshot( coll ); + } + + @Override + public Object getProxy(EntityKey key) { + return delegate.getProxy( key ); + } + + @Override + public void addProxy(EntityKey key, Object proxy) { + delegate.addProxy( key, proxy ); + } + + @Override + public Object removeProxy(EntityKey key) { + return delegate.removeProxy( key ); + } + + @Override + public EntityHolder claimEntityHolderIfPossible(EntityKey key, Object entity, JdbcValuesSourceProcessingState processingState, EntityInitializer initializer) { + return delegate.claimEntityHolderIfPossible( key, entity, processingState, initializer ); + } + + @Override + public EntityHolder addEntityHolder(EntityKey key, Object entity) { + return delegate.addEntityHolder( key, entity ); + } + + @Override + public EntityHolder getEntityHolder(EntityKey key) { + return delegate.getEntityHolder( key ); + } + + @Override + public boolean containsEntityHolder(EntityKey key) { + return delegate.containsEntityHolder( key ); + } + + @Override + public EntityHolder removeEntityHolder(EntityKey key) { + return delegate.removeEntityHolder( key ); + } + + @Override + public void postLoad(JdbcValuesSourceProcessingState processingState, Consumer loadedConsumer) { + delegate.postLoad( processingState, loadedConsumer ); + } + + @Internal + @Override + public Map getEntitiesByKey() { + return delegate.getEntitiesByKey(); + } + + @Internal + @Override + public Map getEntityHoldersByKey() { + return delegate.getEntityHoldersByKey(); + } + + @Override + public Map.Entry[] reentrantSafeEntityEntries() { + return delegate.reentrantSafeEntityEntries(); + } + + @Override + public int getNumberOfManagedEntities() { + return delegate.getNumberOfManagedEntities(); + } + + @Internal + @Override + public Map, CollectionEntry> getCollectionEntries() { + return delegate.getCollectionEntries(); + } + + @Override + public void forEachCollectionEntry(BiConsumer, CollectionEntry> action, boolean concurrent) { + delegate.forEachCollectionEntry( action, concurrent ); + } + + @Deprecated + @Override + public Map> getCollectionsByKey() { + return delegate.getCollectionsByKey(); + } + + @Override + public int getCascadeLevel() { + return delegate.getCascadeLevel(); + } + + @Override + public int incrementCascadeLevel() { + return delegate.incrementCascadeLevel(); + } + + @Override + public int decrementCascadeLevel() { + return delegate.decrementCascadeLevel(); + } + + @Override + public boolean isFlushing() { + return delegate.isFlushing(); + } + + @Override + public void setFlushing(boolean flushing) { + delegate.setFlushing( flushing ); + } + + @Override + public void beforeLoad() { + delegate.beforeLoad(); + } + + @Override + public void afterLoad() { + delegate.afterLoad(); + } + + @Override + public boolean isLoadFinished() { + return delegate.isLoadFinished(); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public Object getOwnerId(String entityName, String propertyName, Object childEntity, Map mergeMap) { + return delegate.getOwnerId( entityName, propertyName, childEntity, mergeMap ); + } + + @Override + public Object getIndexInOwner(String entity, String property, Object childObject, Map mergeMap) { + return delegate.getIndexInOwner( entity, property, childObject, mergeMap ); + } + + @Override + public void addNullProperty(EntityKey ownerKey, String propertyName) { + delegate.addNullProperty( ownerKey, propertyName ); + } + + @Override + public boolean isPropertyNull(EntityKey ownerKey, String propertyName) { + return delegate.isPropertyNull( ownerKey, propertyName ); + } + + @Override + public boolean isDefaultReadOnly() { + return delegate.isDefaultReadOnly(); + } + + @Override + public void setDefaultReadOnly(boolean readOnly) { + delegate.setDefaultReadOnly( readOnly ); + } + + @Override + public boolean isReadOnly(Object entityOrProxy) { + return delegate.isReadOnly( entityOrProxy ); + } + + @Override + public void setReadOnly(Object entityOrProxy, boolean readOnly) { + delegate.setReadOnly( entityOrProxy, readOnly ); + } + + @Override + public boolean isRemovingOrphanBeforeUpdates() { + return delegate.isRemovingOrphanBeforeUpdates(); + } + + @Override + public void beginRemoveOrphanBeforeUpdates() { + delegate.beginRemoveOrphanBeforeUpdates(); + } + + @Override + public void endRemoveOrphanBeforeUpdates() { + delegate.endRemoveOrphanBeforeUpdates(); + } + + @Override + public void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Object generatedId) { + delegate.replaceDelayedEntityIdentityInsertKeys( oldKey, generatedId ); + } + + @Internal + @Override + public void replaceEntityEntryRowId(Object entity, Object rowId) { + delegate.replaceEntityEntryRowId( entity, rowId ); + } + + @Override + public void addChildParent(Object child, Object parent) { + delegate.addChildParent( child, parent ); + } + + @Override + public void removeChildParent(Object child) { + delegate.removeChildParent( child ); + } + + @Override + public void registerInsertedKey(EntityPersister persister, Object id) { + delegate.registerInsertedKey( persister, id ); + } + + @Override + public boolean wasInsertedDuringTransaction(EntityPersister persister, Object id) { + return delegate.wasInsertedDuringTransaction( persister, id ); + } + + @Override + public boolean containsNullifiableEntityKey(Supplier sek) { + return delegate.containsNullifiableEntityKey( sek ); + } + + @Override + public void registerNullifiableEntityKey(EntityKey key) { + delegate.registerNullifiableEntityKey( key ); + } + + @Override + public boolean isNullifiableEntityKeysEmpty() { + return delegate.isNullifiableEntityKeysEmpty(); + } + + @Override + public boolean containsDeletedUnloadedEntityKey(EntityKey ek) { + return delegate.containsDeletedUnloadedEntityKey( ek ); + } + + @Override + public void registerDeletedUnloadedEntityKey(EntityKey key) { + delegate.registerDeletedUnloadedEntityKey( key ); + } + + @Override + public void removeDeletedUnloadedEntityKey(EntityKey key) { + delegate.removeDeletedUnloadedEntityKey( key ); + } + + @Override + public boolean containsDeletedUnloadedEntityKeys() { + return delegate.containsDeletedUnloadedEntityKeys(); + } + + @Override + public int getCollectionEntriesSize() { + return delegate.getCollectionEntriesSize(); + } + + @Override + public CollectionEntry removeCollectionEntry(PersistentCollection collection) { + return delegate.removeCollectionEntry( collection ); + } + + @Override + public void clearCollectionsByKey() { + delegate.clearCollectionsByKey(); + } + + @Override + public PersistentCollection addCollectionByKey(CollectionKey collectionKey, PersistentCollection persistentCollection) { + return delegate.addCollectionByKey( collectionKey, persistentCollection ); + } + + @Override + public void removeCollectionByKey(CollectionKey collectionKey) { + delegate.removeCollectionByKey( collectionKey ); + } + + @Internal + @Override + public Map getEntitySnapshotsByKey() { + return delegate.getEntitySnapshotsByKey(); + } + + @Override + @Internal + public Map getOrInitializeEntitySnapshotsByKey() { + return delegate.getOrInitializeEntitySnapshotsByKey(); + } + + @Override + public Iterator managedEntitiesIterator() { + return delegate.managedEntitiesIterator(); + } + + @Override + public NaturalIdResolutions getNaturalIdResolutions() { + return delegate.getNaturalIdResolutions(); + } +} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/EntityTypes.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/EntityTypes.java index fb1c29fe4..0bb0c75ae 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/EntityTypes.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/EntityTypes.java @@ -76,8 +76,7 @@ public static CompletionStage resolve(EntityType entityType, Object idOr * @see OneToOneType#isNull(Object, SharedSessionContractImplementor) */ static boolean isNull(EntityType entityType, Object owner, SharedSessionContractImplementor session) { - if ( entityType instanceof OneToOneType ) { - OneToOneType type = (OneToOneType) entityType; + if ( entityType instanceof OneToOneType type ) { String propertyName = type.getPropertyName(); if ( propertyName != null ) { final EntityPersister ownerPersister = session.getFactory() @@ -126,7 +125,7 @@ static CompletionStage loadByUniqueKey( entityName, uniqueKeyPropertyName, key, - entityType.getIdentifierOrUniqueKeyType( factory ), + entityType.getIdentifierOrUniqueKeyType( factory.getRuntimeMetamodels() ), factory ); @@ -273,7 +272,7 @@ private static CompletionStage resolveIdOrUniqueKey( .reactiveFetch( id, true ) .thenCompose( fetched -> { Object idOrUniqueKey = entityType - .getIdentifierOrUniqueKeyType( session.getFactory() ) + .getIdentifierOrUniqueKeyType( session.getFactory().getRuntimeMetamodels() ) .replace( fetched, null, session, owner, copyCache ); if ( idOrUniqueKey instanceof CompletionStage ) { return ( (CompletionStage) idOrUniqueKey ) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ForeignKeys.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ForeignKeys.java index 5a77bd9f6..087623e44 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ForeignKeys.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ForeignKeys.java @@ -11,6 +11,7 @@ import org.hibernate.TransientObjectException; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.engine.internal.NonNullableTransientDependencies; +import org.hibernate.engine.internal.ReactivePersistenceContextAdapter; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SelfDirtinessTracker; diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRecreateAction.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRecreateAction.java index 008755086..37f8eaa7e 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRecreateAction.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRecreateAction.java @@ -56,7 +56,7 @@ public void execute() throws HibernateException { } private void preRecreate() { - getFastSessionServices() + getEventListenerGroups() .eventListenerGroup_PRE_COLLECTION_RECREATE .fireLazyEventOnEachListener( this::newPreCollectionRecreateEvent, PreCollectionRecreateEventListener::onPreRecreateCollection ); } @@ -66,7 +66,7 @@ private PreCollectionRecreateEvent newPreCollectionRecreateEvent() { } private void postRecreate() { - getFastSessionServices() + getEventListenerGroups() .eventListenerGroup_POST_COLLECTION_RECREATE .fireLazyEventOnEachListener( this::newPostCollectionRecreateEvent, PostCollectionRecreateEventListener::onPostRecreateCollection ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRemoveAction.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRemoveAction.java index 4b086cf34..0f2bdefea 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRemoveAction.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionRemoveAction.java @@ -100,7 +100,8 @@ public void execute() throws HibernateException { } private void preRemove() { - getFastSessionServices().eventListenerGroup_PRE_COLLECTION_REMOVE + getEventListenerGroups() + .eventListenerGroup_PRE_COLLECTION_REMOVE .fireLazyEventOnEachListener( this::newPreCollectionRemoveEvent, PreCollectionRemoveEventListener::onPreRemoveCollection ); } @@ -115,7 +116,8 @@ private PreCollectionRemoveEvent newPreCollectionRemoveEvent() { } private void postRemove() { - getFastSessionServices().eventListenerGroup_POST_COLLECTION_REMOVE + getEventListenerGroups() + .eventListenerGroup_POST_COLLECTION_REMOVE .fireLazyEventOnEachListener( this::newPostCollectionRemoveEvent, PostCollectionRemoveEventListener::onPostRemoveCollection ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionUpdateAction.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionUpdateAction.java index eae872d56..8806b3e9d 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionUpdateAction.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveCollectionUpdateAction.java @@ -118,7 +118,8 @@ public void execute() throws HibernateException { } private void preUpdate() { - getFastSessionServices().eventListenerGroup_PRE_COLLECTION_UPDATE + getEventListenerGroups() + .eventListenerGroup_PRE_COLLECTION_UPDATE .fireLazyEventOnEachListener( this::newPreCollectionUpdateEvent, PreCollectionUpdateEventListener::onPreUpdateCollection ); } @@ -132,7 +133,8 @@ private PreCollectionUpdateEvent newPreCollectionUpdateEvent() { } private void postUpdate() { - getFastSessionServices().eventListenerGroup_POST_COLLECTION_UPDATE + getEventListenerGroups() + .eventListenerGroup_POST_COLLECTION_UPDATE .fireLazyEventOnEachListener( this::newPostCollectionUpdateEvent, PostCollectionUpdateEventListener::onPostUpdateCollection ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactivePersistenceContextAdapter.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactivePersistenceContextAdapter.java deleted file mode 100644 index 33750cc0d..000000000 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactivePersistenceContextAdapter.java +++ /dev/null @@ -1,134 +0,0 @@ -/* Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.reactive.engine.impl; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.concurrent.CompletionStage; -import java.util.function.Consumer; - -import org.hibernate.HibernateException; -import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.engine.internal.StatefulPersistenceContext; -import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.reactive.logging.impl.Log; -import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; -import org.hibernate.reactive.session.ReactiveSession; - -import static java.lang.invoke.MethodHandles.lookup; -import static org.hibernate.pretty.MessageHelper.infoString; -import static org.hibernate.reactive.logging.impl.LoggerFactory.make; -import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; -import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; - -/** - * Add reactive methods to a {@link PersistenceContext}. - */ -public class ReactivePersistenceContextAdapter extends StatefulPersistenceContext { - - private static final Log LOG = make( Log.class, lookup() ); - - private HashMap entitySnapshotsByKey; - - /** - * Constructs a PersistentContext, bound to the given session. - * - * @param session The session "owning" this context. - */ - public ReactivePersistenceContextAdapter(SharedSessionContractImplementor session) { - super( session ); - } - - public CompletionStage reactiveInitializeNonLazyCollections() throws HibernateException { - final NonLazyCollectionInitializer initializer = new NonLazyCollectionInitializer(); - initializeNonLazyCollections( initializer ); - return initializer.stage; - } - - private class NonLazyCollectionInitializer implements Consumer> { - CompletionStage stage = voidFuture(); - - @Override - public void accept(PersistentCollection nonLazyCollection) { - if ( !nonLazyCollection.wasInitialized() ) { - stage = stage.thenCompose( v -> ( (ReactiveSession) getSession() ) - .reactiveInitializeCollection( nonLazyCollection, false ) ); - } - } - } - - /** - * @deprecated use {@link #reactiveInitializeNonLazyCollections} instead. - */ - @Deprecated - @Override - public void initializeNonLazyCollections() { - // still called by ResultSetProcessorImpl, so can't throw UnsupportedOperationException - } - - @Deprecated - @Override - public Object[] getDatabaseSnapshot(Object id, EntityPersister persister) throws HibernateException { - throw LOG.nonReactiveMethodCall( "reactiveGetDatabaseSnapshot" ); - } - - private static final Object[] NO_ROW = new Object[]{ StatefulPersistenceContext.NO_ROW }; - - public CompletionStage reactiveGetDatabaseSnapshot(Object id, EntityPersister persister) - throws HibernateException { - - SessionImplementor session = (SessionImplementor) getSession(); - final EntityKey key = session.generateEntityKey( id, persister ); - final Object[] cached = entitySnapshotsByKey == null ? null : entitySnapshotsByKey.get( key ); - if ( cached != null ) { - return completedFuture( cached == NO_ROW ? null : cached ); - } - else { - return ( (ReactiveEntityPersister) persister ) - .reactiveGetDatabaseSnapshot( id, session ) - .thenApply( snapshot -> { - if ( entitySnapshotsByKey == null ) { - entitySnapshotsByKey = new HashMap<>( 8 ); - } - entitySnapshotsByKey.put( key, snapshot == null ? NO_ROW : snapshot ); - return snapshot; - } ); - } - } - - //All below methods copy/pasted from superclass because entitySnapshotsByKey is private: - - @Override - public Object[] getCachedDatabaseSnapshot(EntityKey key) { - final Object[] snapshot = entitySnapshotsByKey == null ? null : entitySnapshotsByKey.get( key ); - if ( snapshot == NO_ROW ) { - throw new IllegalStateException( - "persistence context reported no row snapshot for " - + infoString( key.getEntityName(), key.getIdentifier() ) - ); - } - return snapshot; - } - - @Override - public void clear() { - super.clear(); - entitySnapshotsByKey = null; - } - - @Override - public Object removeEntity(EntityKey key) { - Object result = super.removeEntity(key); - if (entitySnapshotsByKey != null ) { - entitySnapshotsByKey.remove(key); - } - return result; - } -} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/ReactiveResolveNaturalIdEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/ReactiveResolveNaturalIdEventListener.java deleted file mode 100644 index fe0fbb96a..000000000 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/ReactiveResolveNaturalIdEventListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.reactive.event; - -import org.hibernate.event.spi.ResolveNaturalIdEvent; - -import java.util.concurrent.CompletionStage; - -/** - * Defines the contract for handling of resolve natural id events generated from a session. - * - * @author Eric Dalquist - * @author Steve Ebersole - * - * @see org.hibernate.event.spi.ResolveNaturalIdEventListener - */ -public interface ReactiveResolveNaturalIdEventListener { - - /** - * Handle the given resolve natural id event. - * - * @param event The resolve natural id event to be handled. - */ - CompletionStage onReactiveResolveNaturalId(ResolveNaturalIdEvent event); - -} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/AbstractReactiveFlushingEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/AbstractReactiveFlushingEventListener.java index 2772cc15d..b257229b2 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/AbstractReactiveFlushingEventListener.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/AbstractReactiveFlushingEventListener.java @@ -139,9 +139,8 @@ protected void logFlushResults(FlushEvent event) { session.getActionQueue().numberOfCollectionRemovals(), persistenceContext.getCollectionEntriesSize() ); - new EntityPrinter( session.getFactory() ).toString( - persistenceContext.getEntityHoldersByKey().entrySet() - ); + new EntityPrinter( session.getFactory() ) + .logEntities( persistenceContext.getEntityHoldersByKey().entrySet() ); } /** @@ -227,7 +226,7 @@ private int flushEntities(final FlushEvent event, final PersistenceContext persi final EventSource source = event.getSession(); final Iterable flushListeners = source.getFactory() - .getFastSessionServices() + .getEventListenerGroups() .eventListenerGroup_FLUSH_ENTITY .listeners(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveDeleteEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveDeleteEventListener.java index 66151f03b..664b09da3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveDeleteEventListener.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveDeleteEventListener.java @@ -13,7 +13,6 @@ import org.hibernate.TransientObjectException; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; -import org.hibernate.classic.Lifecycle; import org.hibernate.engine.internal.CascadePoint; import org.hibernate.engine.internal.Nullability; import org.hibernate.engine.spi.EntityEntry; @@ -22,13 +21,13 @@ import org.hibernate.engine.spi.Status; import org.hibernate.event.internal.OnUpdateVisitor; import org.hibernate.event.internal.PostDeleteEventListenerStandardImpl; +import org.hibernate.event.service.spi.EventListenerGroups; import org.hibernate.event.service.spi.JpaBootstrapSensitive; import org.hibernate.event.spi.DeleteContext; import org.hibernate.event.spi.DeleteEvent; import org.hibernate.event.spi.DeleteEventListener; import org.hibernate.event.spi.EventSource; import org.hibernate.internal.EmptyInterceptor; -import org.hibernate.internal.FastSessionServices; import org.hibernate.jpa.event.spi.CallbackRegistry; import org.hibernate.jpa.event.spi.CallbackRegistryConsumer; import org.hibernate.jpa.event.spi.CallbackType; @@ -205,17 +204,6 @@ private CompletionStage fetchAndDelete(DeleteEvent event, DeleteContext tr } - protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) { - if ( persister.implementsLifecycle() ) { - LOG.debug( "Calling onDelete()" ); - if ( ( (Lifecycle) entity ).onDelete( session ) ) { - LOG.debug( "Deletion vetoed by onDelete()" ); - return true; - } - } - return false; - } - private CompletionStage deleteTransientInstance(DeleteEvent event, DeleteContext transientEntities, Object entity) { LOG.trace( "Entity was not persistent in delete processing" ); @@ -291,23 +279,20 @@ private CompletionStage delete( Object version, EntityEntry entry) { callbackRegistry.preRemove( entity ); - if ( !invokeDeleteLifecycle( source, entity, persister ) ) { - return deleteEntity( - source, - entity, - entry, - event.isCascadeDeleteEnabled(), - event.isOrphanRemovalBeforeUpdates(), - persister, - transientEntities - ) - .thenAccept( v -> { - if ( source.getFactory().getSessionFactoryOptions().isIdentifierRollbackEnabled() ) { - persister.resetIdentifier( entity, id, version, source ); - } - } ); - } - return voidFuture(); + return deleteEntity( + source, + entity, + entry, + event.isCascadeDeleteEnabled(), + event.isOrphanRemovalBeforeUpdates(), + persister, + transientEntities + ) + .thenAccept( v -> { + if ( source.getFactory().getSessionFactoryOptions().isIdentifierRollbackEnabled() ) { + persister.resetIdentifier( entity, id, version, source ); + } + } ); } /** @@ -315,7 +300,6 @@ private CompletionStage delete( */ private boolean canBeDeletedWithoutLoading(EventSource source, EntityPersister persister) { return source.getInterceptor() == EmptyInterceptor.INSTANCE - && !persister.implementsLifecycle() && !persister.hasSubclasses() //TODO: should be unnecessary, using EntityPersister.getSubclassPropertyTypeClosure(), etc && !persister.hasCascadeDelete() && !persister.hasNaturalIdentifier() @@ -325,7 +309,7 @@ private boolean canBeDeletedWithoutLoading(EventSource source, EntityPersister p } private static boolean hasCustomEventListeners(EventSource source) { - final FastSessionServices fss = source.getFactory().getFastSessionServices(); + final EventListenerGroups fss = source.getFactory().getEventListenerGroups(); // Bean Validation adds a PRE_DELETE listener // and Envers adds a POST_DELETE listener return fss.eventListenerGroup_PRE_DELETE.count() > 0 diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveLoadEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveLoadEventListener.java index 8f821a986..9804a02f6 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveLoadEventListener.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveLoadEventListener.java @@ -27,8 +27,7 @@ import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.LoadEvent; import org.hibernate.event.spi.LoadEventListener; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.PersistenceContextEntry; +import org.hibernate.loader.internal.CacheLoadHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMappingsList; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; @@ -40,7 +39,6 @@ import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.reactive.event.ReactiveLoadEventListener; -import org.hibernate.reactive.loader.entity.ReactiveCacheEntityLoaderHelper; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; @@ -49,7 +47,10 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; +import static org.hibernate.loader.internal.CacheLoadHelper.loadFromSecondLevelCache; +import static org.hibernate.loader.internal.CacheLoadHelper.loadFromSessionCache; import static org.hibernate.pretty.MessageHelper.infoString; +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; import static org.hibernate.reactive.session.impl.SessionUtil.checkEntityFound; import static org.hibernate.reactive.session.impl.SessionUtil.throwEntityNotFound; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; @@ -399,7 +400,7 @@ private static CompletionStage loadWithProxyFactory(LoadEvent event, Ent if ( proxy != null ) { LOG.trace( "Entity proxy found in session cache" ); - if ( LOG.isDebugEnabled() && HibernateProxy.extractLazyInitializer( proxy ).isUnwrap() ) { + if ( LOG.isDebugEnabled() && extractLazyInitializer( proxy ).isUnwrap() ) { LOG.debug( "Ignoring NO_PROXY to honor laziness" ); } @@ -429,7 +430,7 @@ private static PersistentAttributeInterceptable createBatchLoadableEnhancedProxy } private static Object proxyOrCached(LoadEvent event, EntityPersister persister, EntityKey keyToLoad) { - final Object cachedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( + final Object cachedEntity = loadFromSecondLevelCache( event.getSession(), null, LockMode.NONE, @@ -450,7 +451,7 @@ private static Object proxyOrCached(LoadEvent event, EntityPersister persister, return options.isCheckDeleted() && wasDeleted( persistenceContext, existing ) ? null : existing; } if ( persister.hasSubclasses() ) { - final Object cachedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( + final Object cachedEntity = loadFromSecondLevelCache( event.getSession(), null, LockMode.NONE, @@ -652,9 +653,9 @@ private CompletionStage doLoad( return nullFuture(); } else { - final PersistenceContextEntry persistenceContextEntry = - ReactiveCacheEntityLoaderHelper.INSTANCE.loadFromSessionCache( event, keyToLoad, options ); - final Object entity = persistenceContextEntry.getEntity(); + final CacheLoadHelper.PersistenceContextEntry persistenceContextEntry = + loadFromSessionCache( keyToLoad, event.getLockOptions(), options, event.getSession() ); + final Object entity = persistenceContextEntry.entity(); if ( entity != null ) { return persistenceContextEntry.isManaged() ? initializeIfNecessary( entity ) : nullFuture(); } @@ -668,9 +669,7 @@ private static CompletionStage initializeIfNecessary(Object entity) { if ( isPersistentAttributeInterceptable( entity ) ) { final PersistentAttributeInterceptable interceptable = asPersistentAttributeInterceptable( entity ); final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor(); - if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor) { - final EnhancementAsProxyLazinessInterceptor lazinessInterceptor = - (EnhancementAsProxyLazinessInterceptor) interceptor; + if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor lazinessInterceptor ) { final SharedSessionContractImplementor session = lazinessInterceptor.getLinkedSession(); if ( session == null ) { throw LOG.sessionClosedLazyInitializationException(); @@ -691,7 +690,8 @@ private CompletionStage loadFromCacheOrDatasource( EntityPersister persister, EntityKey keyToLoad) { final EventSource session = event.getSession(); - final Object entity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(event, persister, keyToLoad); + final Object entity = session + .loadFromSecondLevelCache( persister, keyToLoad, event.getInstanceToLoad(), event.getLockMode() ); if ( entity != null ) { if ( LOG.isTraceEnabled() ) { LOG.tracev( @@ -740,6 +740,10 @@ private void cacheNaturalId(LoadEvent event, EntityPersister persister, EventSou * @return The object loaded from the datasource, or null if not found. */ protected CompletionStage loadFromDatasource(LoadEvent event, EntityPersister persister) { + if ( LOG.isTraceEnabled() ) { + LOG.trace( "Entity not resolved in any cache, loading from datastore: " + + infoString( persister, event.getEntityId(), event.getFactory() ) ); + } return ( (ReactiveEntityPersister) persister ) .reactiveLoad( event.getEntityId(), @@ -754,16 +758,14 @@ protected CompletionStage loadFromDatasource(LoadEvent event, EntityPers // persister/loader/initializer sensitive to this fact - possibly // passing LoadType along - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity ); - if ( lazyInitializer != null ) { - entity = lazyInitializer.getImplementation(); - } + final LazyInitializer lazyInitializer = extractLazyInitializer( entity ); + final Object impl = lazyInitializer != null ? lazyInitializer.getImplementation() : entity; final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics(); if ( event.isAssociationFetch() && statistics.isStatisticsEnabled() ) { statistics.fetchEntity( event.getEntityClassName() ); } - return entity; + return impl; } ); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveMergeEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveMergeEventListener.java index 7f258a1d4..e6cc4cd95 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveMergeEventListener.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveMergeEventListener.java @@ -94,7 +94,9 @@ protected Map getMergeMap(MergeContext context) { @Override public CompletionStage reactiveOnMerge(MergeEvent event) throws HibernateException { final EventSource session = event.getSession(); - final EntityCopyObserver entityCopyObserver = createEntityCopyObserver( session ); + final EntityCopyObserver entityCopyObserver = session.getFactory() + .getEntityCopyObserver() + .createEntityCopyObserver(); final MergeContext mergeContext = new MergeContext( session, entityCopyObserver ); return reactiveOnMerge( event, mergeContext ) .thenAccept( v -> entityCopyObserver.topLevelMergeComplete( session ) ) @@ -104,10 +106,6 @@ public CompletionStage reactiveOnMerge(MergeEvent event) throws HibernateE } ); } - private EntityCopyObserver createEntityCopyObserver(final EventSource session) { - return session.getFactory().getFastSessionServices().entityCopyObserverFactory.createEntityCopyObserver(); - } - /** * Handle the given merge event. * diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactivePostLoadEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactivePostLoadEventListener.java index 053c8465f..e1af57441 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactivePostLoadEventListener.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactivePostLoadEventListener.java @@ -6,7 +6,6 @@ package org.hibernate.reactive.event.impl; import org.hibernate.AssertionFailure; -import org.hibernate.classic.Lifecycle; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.PostLoadEvent; @@ -21,7 +20,6 @@ /** * We do two things here: *
    - *
  • Call {@link Lifecycle} interface if necessary
  • *
  • Perform needed {@link EntityEntry#getLockMode()} related processing
  • *
* diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveResolveNaturalIdEventListener.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveResolveNaturalIdEventListener.java deleted file mode 100644 index 783c02ec8..000000000 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/event/impl/DefaultReactiveResolveNaturalIdEventListener.java +++ /dev/null @@ -1,135 +0,0 @@ -/* Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.reactive.event.impl; - -import java.lang.invoke.MethodHandles; -import java.util.concurrent.CompletionStage; - -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.NaturalIdResolutions; -import org.hibernate.event.spi.EventSource; -import org.hibernate.event.spi.ResolveNaturalIdEvent; -import org.hibernate.event.spi.ResolveNaturalIdEventListener; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.reactive.event.ReactiveResolveNaturalIdEventListener; -import org.hibernate.reactive.logging.impl.Log; -import org.hibernate.reactive.logging.impl.LoggerFactory; -import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; -import org.hibernate.stat.spi.StatisticsImplementor; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static org.hibernate.pretty.MessageHelper.infoString; -import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; - -/** - * A reactive {@link org.hibernate.event.internal.DefaultResolveNaturalIdEventListener}. - */ -public class DefaultReactiveResolveNaturalIdEventListener implements ReactiveResolveNaturalIdEventListener, ResolveNaturalIdEventListener { - - private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - - @Override - public void onResolveNaturalId(ResolveNaturalIdEvent event) throws HibernateException { - throw new UnsupportedOperationException(); - } - - @Override - public CompletionStage onReactiveResolveNaturalId(ResolveNaturalIdEvent event) throws HibernateException { - return resolveNaturalId( event ).thenAccept( event::setEntityId ); - } - - /** - * Coordinates the efforts to load a given entity. First, an attempt is - * made to load the entity from the session-level cache. If not found there, - * an attempt is made to locate it in second-level cache. Lastly, an - * attempt is made to load it directly from the datasource. - * - * @param event The load event - * - * @return The loaded entity, or null. - */ - protected CompletionStage resolveNaturalId(ResolveNaturalIdEvent event) { - final EntityPersister persister = event.getEntityPersister(); - - if ( LOG.isTraceEnabled() ) { - LOG.tracev( - "Attempting to resolve: {0}#{1}", - infoString( persister ), - event.getNaturalIdValues() - ); - } - - final Object entityId = resolveFromCache( event ); - if ( entityId != null ) { - if ( LOG.isTraceEnabled() ) { - LOG.tracev( - "Resolved object in cache: {0}#{1}", - infoString( persister ), - event.getNaturalIdValues() ); - } - return completedFuture( entityId ); - } - - if ( LOG.isTraceEnabled() ) { - LOG.tracev( - "Object not resolved in any cache: {0}#{1}", - infoString( persister ), - event.getNaturalIdValues() - ); - } - - return loadFromDatasource( event ); - } - - /** - * Attempts to resolve the entity id corresponding to the event's natural id values from the session - * - * @param event The load event - * @return The entity from the cache, or null. - */ - protected Object resolveFromCache(ResolveNaturalIdEvent event) { - return getNaturalIdResolutions( event ) - .findCachedIdByNaturalId( event.getOrderedNaturalIdValues(), event.getEntityPersister() ); - } - - /** - * Performs the process of loading an entity from the configured - * underlying datasource. - * - * @param event The load event - * - * @return The object loaded from the datasource, or null if not found. - */ - protected CompletionStage loadFromDatasource(ResolveNaturalIdEvent event) { - final EventSource session = event.getSession(); - final EntityPersister entityPersister = event.getEntityPersister(); - final StatisticsImplementor statistics = session.getFactory().getStatistics(); - final boolean statisticsEnabled = statistics.isStatisticsEnabled(); - final long startTime = statisticsEnabled ? System.nanoTime() : 0; - - return ( (ReactiveEntityPersister) entityPersister ) - .reactiveLoadEntityIdByNaturalId( event.getOrderedNaturalIdValues(), event.getLockOptions(), session ) - .thenApply( pk -> { - if ( statisticsEnabled ) { - long milliseconds = MILLISECONDS.convert( System.nanoTime() - startTime, NANOSECONDS ); - statistics.naturalIdQueryExecuted( entityPersister.getRootEntityName(), milliseconds ); - } - - //PK can be null if the entity doesn't exist - if ( pk != null ) { - getNaturalIdResolutions( event ) - .cacheResolutionFromLoad( pk, event.getOrderedNaturalIdValues(), entityPersister ); - } - - return pk; - } ); - } - - private static NaturalIdResolutions getNaturalIdResolutions(ResolveNaturalIdEvent event) { - return event.getSession().getPersistenceContextInternal().getNaturalIdResolutions(); - } -} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/DatabaseSnapshotExecutor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/DatabaseSnapshotExecutor.java index 3fdd5acf1..33e8465b2 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/DatabaseSnapshotExecutor.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/DatabaseSnapshotExecutor.java @@ -79,7 +79,7 @@ class DatabaseSnapshotExecutor { DatabaseSnapshotExecutor::visitEmptyFetchList, true, new LoadQueryInfluencers( sessionFactory ), - sessionFactory + sessionFactory.getSqlTranslationEngine() ); final NavigablePath rootPath = new NavigablePath( entityDescriptor.getEntityName() ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderArrayParam.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderArrayParam.java index efeafdd02..0960a2ebc 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderArrayParam.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderArrayParam.java @@ -18,9 +18,9 @@ import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.MultiKeyLoadHelper; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; +import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping; -import org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor; import org.hibernate.query.spi.QueryOptions; import org.hibernate.reactive.sql.exec.internal.StandardReactiveSelectExecutor; import org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer; @@ -34,7 +34,6 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParametersList; import org.hibernate.sql.results.internal.RowTransformerStandardImpl; -import org.hibernate.type.BasicType; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; @@ -65,18 +64,14 @@ public ReactiveCollectionBatchLoaderArrayParam( ); } - final SimpleForeignKeyDescriptor keyDescriptor = (SimpleForeignKeyDescriptor) getLoadable().getKeyDescriptor(); - + final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); + final JdbcMapping jdbcMapping = keyDescriptor.getSingleJdbcMapping(); + final Class jdbcJavaTypeClass = jdbcMapping.getJdbcJavaType().getJavaTypeClass(); arrayElementType = keyDescriptor.getJavaType().getJavaTypeClass(); - Class arrayClass = Array.newInstance( arrayElementType, 0 ).getClass(); - final BasicType arrayBasicType = getSessionFactory().getTypeConfiguration() - .getBasicTypeRegistry() - .getRegisteredType( arrayClass ); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - arrayBasicType, - keyDescriptor.getJdbcMapping(), - arrayClass, + keyDescriptor.getSingleJdbcMapping(), + jdbcJavaTypeClass, getSessionFactory() ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderArrayParam.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderArrayParam.java index 9ff3c2ba7..ba69fd407 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderArrayParam.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderArrayParam.java @@ -63,12 +63,10 @@ public ReactiveEntityBatchLoaderArrayParam( } identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping(); - final Class arrayClass = - Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass(); + final Class idClass = identifierMapping.getJavaType().getJavaTypeClass(); arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ), identifierMapping.getJdbcMapping(), - arrayClass, + idClass, sessionFactory ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderArrayParam.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderArrayParam.java index fd7cb8794..fa0b1885d 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderArrayParam.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderArrayParam.java @@ -21,17 +21,15 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.event.spi.EventSource; -import org.hibernate.event.spi.LoadEvent; -import org.hibernate.event.spi.LoadEventListener; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; -import org.hibernate.loader.ast.internal.LoaderHelper; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.MultiIdEntityLoaderArrayParam; import org.hibernate.loader.ast.internal.MultiKeyLoadLogging; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.internal.CacheLoadHelper.PersistenceContextEntry; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.JdbcMapping; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.spi.QueryOptions; import org.hibernate.reactive.sql.exec.internal.StandardReactiveSelectExecutor; import org.hibernate.reactive.sql.results.spi.ReactiveListResultsConsumer; @@ -44,11 +42,12 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParametersList; import org.hibernate.sql.results.internal.RowTransformerStandardImpl; -import org.hibernate.type.BasicType; +import static org.hibernate.event.spi.LoadEventListener.GET; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.resolveArrayJdbcMapping; +import static org.hibernate.loader.internal.CacheLoadHelper.loadFromSessionCache; import static org.hibernate.reactive.loader.ast.internal.ReactiveLoaderHelper.loadByArrayParameter; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; import static org.hibernate.reactive.util.impl.CompletionStages.loop; @@ -67,15 +66,12 @@ public ReactiveMultiIdEntityLoaderArrayParam( SessionFactoryImplementor sessionFactory) { super( entityDescriptor, sessionFactory ); final Class arrayClass = createTypedArray( 0 ).getClass(); - JdbcMapping jdbcMapping = getIdentifierMapping().getJdbcMapping(); - BasicType registeredType = getSessionFactory().getTypeConfiguration() - .getBasicTypeRegistry() - .getRegisteredType( arrayClass ); - JdbcMapping arrayJdbcMapping1 = resolveArrayJdbcMapping( registeredType, jdbcMapping, arrayClass, getSessionFactory() ); -// JavaType objectJavaType = getSessionFactory().getTypeConfiguration() -// .getJavaTypeRegistry() -// .resolveDescriptor( ReactiveArrayJdbcType.class ); - arrayJdbcMapping = arrayJdbcMapping1; + final Class idClass = getIdentifierMapping().getJavaType().getJavaTypeClass(); + arrayJdbcMapping = resolveArrayJdbcMapping( + getIdentifierMapping().getJdbcMapping(), + idClass, + getSessionFactory() + ); jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); } @@ -113,24 +109,17 @@ protected CompletionStage> performOrderedMultiLoad( final EntityKey entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); if ( loadOptions.isSessionCheckingEnabled() || loadOptions.isSecondLevelCacheCheckingEnabled() ) { - LoadEvent loadEvent = new LoadEvent( - id, - getLoadable().getJavaType().getJavaTypeClass().getName(), - lockOptions, - session, - LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session ) - ); - Object managedEntity = null; if ( loadOptions.isSessionCheckingEnabled() ) { // look for it in the Session first - final CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.loadFromSessionCacheStatic( - loadEvent, + final PersistenceContextEntry persistenceContextEntry = loadFromSessionCache( entityKey, - LoadEventListener.GET + lockOptions, + GET, + session ); - managedEntity = persistenceContextEntry.getEntity(); + managedEntity = persistenceContextEntry.entity(); if ( managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() @@ -142,12 +131,9 @@ protected CompletionStage> performOrderedMultiLoad( } if ( managedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled() ) { + final EntityPersister persister = getLoadable().getEntityPersister(); // look for it in the SessionFactory - managedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - loadEvent, - getLoadable().getEntityPersister(), - entityKey - ); + managedEntity = session.loadFromSecondLevelCache( persister, entityKey, null, lockOptions.getLockMode() ); } if ( managedEntity != null ) { @@ -217,9 +203,7 @@ protected CompletionStage> performOrderedMultiLoad( } ) .thenApply( ignore -> { final PersistenceContext persistenceContext = session.getPersistenceContext(); - for ( int i = 0; i < idsToLoadFromDatabaseResultIndexes.size(); i++ ) { - final Integer resultIndex = idsToLoadFromDatabaseResultIndexes.get( i ); - + for ( final Integer resultIndex : idsToLoadFromDatabaseResultIndexes ) { // the element value at this position in the result List should be // the EntityKey for that entity - reuse it final EntityKey entityKey = (EntityKey) result.get( resultIndex ); @@ -337,32 +321,24 @@ protected final K[] processResolvableEntities( for ( int i = 0; i < ids.length; i++ ) { final Object id; if ( coerce ) { - //noinspection unchecked - id = (K) getLoadable().getIdentifierMapping().getJavaType().coerce( ids[i], session ); + id = getLoadable().getIdentifierMapping().getJavaType().coerce( ids[i], session ); } else { id = ids[i]; } final EntityKey entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); - final LoadEvent loadEvent = new LoadEvent( - id, - getLoadable().getJavaType().getJavaTypeClass().getName(), - lockOptions, - session, - LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session ) - ); - Object resolvedEntity = null; // look for it in the Session first - final CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.loadFromSessionCacheStatic( - loadEvent, + final PersistenceContextEntry persistenceContextEntry = loadFromSessionCache( entityKey, - LoadEventListener.GET + lockOptions, + GET, + session ); if ( loadOptions.isSessionCheckingEnabled() ) { - resolvedEntity = persistenceContextEntry.getEntity(); + resolvedEntity = persistenceContextEntry.entity(); if ( resolvedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() @@ -374,11 +350,8 @@ protected final K[] processResolvableEntities( } if ( resolvedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled() ) { - resolvedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - loadEvent, - getLoadable().getEntityPersister(), - entityKey - ); + final EntityPersister persister = getLoadable().getEntityPersister(); + resolvedEntity = session.loadFromSecondLevelCache( persister, entityKey, null, lockOptions.getLockMode() ); } if ( resolvedEntity != null ) { @@ -391,7 +364,6 @@ protected final K[] processResolvableEntities( if ( nonResolvedIds == null ) { nonResolvedIds = new ArrayList<>(); } - //noinspection unchecked,CastCanBeRemovedNarrowingVariableType nonResolvedIds.add( (K) id ); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderStandard.java index 9a87f2359..92f4e996a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveMultiIdEntityLoaderStandard.java @@ -20,19 +20,15 @@ import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.event.spi.EventSource; -import org.hibernate.event.spi.LoadEvent; -import org.hibernate.event.spi.LoadEventListener; import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; -import org.hibernate.loader.ast.internal.LoaderHelper; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.internal.CacheLoadHelper.PersistenceContextEntry; import org.hibernate.mapping.PersistentClass; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.query.spi.QueryOptions; @@ -50,6 +46,8 @@ import org.hibernate.sql.exec.spi.JdbcParametersList; import org.hibernate.sql.results.internal.RowTransformerStandardImpl; +import static org.hibernate.event.spi.LoadEventListener.GET; +import static org.hibernate.loader.internal.CacheLoadHelper.loadFromSessionCache; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; @@ -114,24 +112,17 @@ protected CompletionStage> performOrderedMultiLoad( final EntityKey entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); if ( loadOptions.isSessionCheckingEnabled() || loadOptions.isSecondLevelCacheCheckingEnabled() ) { - LoadEvent loadEvent = new LoadEvent( - id, - getLoadable().getJavaType().getJavaTypeClass().getName(), - lockOptions, - session, - LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session ) - ); - Object managedEntity = null; if ( loadOptions.isSessionCheckingEnabled() ) { // look for it in the Session first - CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache( - loadEvent, + PersistenceContextEntry persistenceContextEntry = loadFromSessionCache( entityKey, - LoadEventListener.GET + lockOptions, + GET, + session ); - managedEntity = persistenceContextEntry.getEntity(); + managedEntity = persistenceContextEntry.entity(); if ( managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry.isManaged() ) { // put a null in the result @@ -141,12 +132,10 @@ protected CompletionStage> performOrderedMultiLoad( } if ( managedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled() ) { + final EntityPersister persister = getLoadable().getEntityPersister(); // look for it in the SessionFactory - managedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - loadEvent, - getLoadable().getEntityPersister(), - entityKey - ); + managedEntity = session + .loadFromSecondLevelCache( persister, entityKey, null, lockOptions.getLockMode() ); } if ( managedEntity != null ) { @@ -324,34 +313,26 @@ protected CompletionStage> performUnorderedMultiLoad( final List nonManagedIds = new ArrayList<>(); final boolean coerce = !getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled(); - for ( int i = 0; i < ids.length; i++ ) { + for ( Object o : ids ) { final Object id = coerce - ? getEntityDescriptor().getIdentifierMapping().getJavaType().coerce( ids[i], session ) - : ids[i]; + ? getEntityDescriptor().getIdentifierMapping().getJavaType().coerce( o, session ) + : o; final EntityKey entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); - LoadEvent loadEvent = new LoadEvent( - id, - getLoadable().getJavaType().getJavaTypeClass().getName(), - lockOptions, - session, - getReadOnlyFromLoadQueryInfluencers( session ) - ); - - Object managedEntity = null; + Object cachedEntity = null; // look for it in the Session first - CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.INSTANCE - .loadFromSessionCache( - loadEvent, - entityKey, - LoadEventListener.GET - ); + PersistenceContextEntry persistenceContextEntry = loadFromSessionCache( + entityKey, + lockOptions, + GET, + session + ); if ( loadOptions.isSessionCheckingEnabled() ) { - managedEntity = persistenceContextEntry.getEntity(); + cachedEntity = persistenceContextEntry.entity(); - if ( managedEntity != null + if ( cachedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry.isManaged() ) { foundAnyManagedEntities = true; @@ -360,18 +341,20 @@ protected CompletionStage> performUnorderedMultiLoad( } } - if ( managedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled() ) { - managedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - loadEvent, - getLoadable().getEntityPersister(), - entityKey + if ( cachedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled() ) { + final EntityPersister persister = getLoadable().getEntityPersister(); + cachedEntity = session.loadFromSecondLevelCache( + persister, + entityKey, + null, + lockOptions.getLockMode() ); } - if ( managedEntity != null ) { + if ( cachedEntity != null ) { foundAnyManagedEntities = true; //noinspection unchecked - result.add( (T) managedEntity ); + result.add( (T) cachedEntity ); } else { nonManagedIds.add( id ); @@ -427,14 +410,4 @@ protected CompletionStage> performUnorderedMultiLoad( } ) .thenApply( v -> result ); } - - private Boolean getReadOnlyFromLoadQueryInfluencers(SharedSessionContractImplementor session) { - Boolean readOnly = null; - final LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers(); - if ( loadQueryInfluencers != null ) { - readOnly = loadQueryInfluencers.getReadOnly(); - } - return readOnly; - } - } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveNaturalIdLoaderDelegate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveNaturalIdLoaderDelegate.java index 56fef5be9..ede1c6cf7 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveNaturalIdLoaderDelegate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveNaturalIdLoaderDelegate.java @@ -238,7 +238,7 @@ public CompletionStage reactiveSelectByNaturalId( fetchProcessor, true, new LoadQueryInfluencers( sessionFactory ), - sessionFactory + sessionFactory.getSqlTranslationEngine() ); final TableGroup rootTableGroup = entityDescriptor().createRootTableGroup( diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveStandardBatchLoaderFactory.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveStandardBatchLoaderFactory.java index 5d5c03fb5..fa5d075ba 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveStandardBatchLoaderFactory.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveStandardBatchLoaderFactory.java @@ -33,7 +33,7 @@ public EntityBatchLoader createEntityBatchLoader( // NOTE : don't use the EntityIdentifierMapping here because it will not be known until later final Type identifierType = entityDescriptor.getEntityPersister().getIdentifierType(); - final int idColumnCount = identifierType.getColumnSpan( factory ); + final int idColumnCount = identifierType.getColumnSpan( factory.getRuntimeMetamodels() ); if ( idColumnCount == 1 && MultiKeyLoadHelper.supportsSqlArrayType( dialect ) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/entity/ReactiveCacheEntityLoaderHelper.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/entity/ReactiveCacheEntityLoaderHelper.java deleted file mode 100644 index 703148cd7..000000000 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/entity/ReactiveCacheEntityLoaderHelper.java +++ /dev/null @@ -1,148 +0,0 @@ -/* Hibernate, Relational Persistence for Idiomatic Java - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright: Red Hat Inc. and Hibernate Authors - */ -package org.hibernate.reactive.loader.entity; - -import static org.hibernate.loader.ast.internal.LoaderHelper.upgradeLock; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.ObjectDeletedException; -import org.hibernate.cache.spi.access.EntityDataAccess; -import org.hibernate.cache.spi.access.SoftLock; -import org.hibernate.engine.spi.EntityEntry; -import org.hibernate.engine.spi.EntityKey; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.engine.spi.Status; -import org.hibernate.event.spi.EventSource; -import org.hibernate.event.spi.LoadEvent; -import org.hibernate.event.spi.LoadEventListener; -import org.hibernate.internal.CoreLogging; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.EntityStatus; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.PersistenceContextEntry; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; -import org.hibernate.sql.results.LoadingLogger; - -/** - * @author Gavin King - * - * @see org.hibernate.loader.ast.internal.CacheEntityLoaderHelper - */ -public class ReactiveCacheEntityLoaderHelper { - - public static final ReactiveCacheEntityLoaderHelper INSTANCE = new ReactiveCacheEntityLoaderHelper(); - - private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ReactiveCacheEntityLoaderHelper.class ); - - private ReactiveCacheEntityLoaderHelper() {} - - /** - * Attempts to locate the entity in the session-level cache. - *

- * If allowed to return nulls, then if the entity happens to be found in - * the session cache, we check the entity type for proper handling - * of entity hierarchies. - *

- * If checkDeleted was set to true, then if the entity is found in the - * session-level cache, its current status within the session cache - * is checked to see if it has previously been scheduled for deletion. - * - * @param event The load event - * @param keyToLoad The EntityKey representing the entity to be loaded. - * @param options The load options. - * - * @return The entity from the session-level cache, or null. - * - * @throws HibernateException Generally indicates problems applying a lock-mode. - */ - public PersistenceContextEntry loadFromSessionCache( - final LoadEvent event, - final EntityKey keyToLoad, - final LoadEventListener.LoadType options) throws HibernateException { - - SessionImplementor session = event.getSession(); - Object old = session.getEntityUsingInterceptor( keyToLoad ); - - if ( old != null ) { - // this object was already loaded - EntityEntry oldEntry = session.getPersistenceContext().getEntry( old ); - if ( options.isCheckDeleted() ) { - if ( oldEntry.getStatus().isDeletedOrGone() ) { - LoadingLogger.LOGGER.debug( - "Load request found matching entity in context, but it is scheduled for removal; returning null" ); - return new PersistenceContextEntry( old, EntityStatus.REMOVED_ENTITY_MARKER ); - } - } - if ( options.isAllowNulls() ) { - final EntityPersister persister = event.getSession() - .getFactory() - .getRuntimeMetamodels() - .getMappingMetamodel() - .getEntityDescriptor( keyToLoad.getEntityName() ); - if ( !persister.isInstance( old ) ) { - LOG.debug( - "Load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null" - ); - return new PersistenceContextEntry( old, EntityStatus.INCONSISTENT_RTN_CLASS_MARKER ); - } - } - upgradeLock( old, oldEntry, event.getLockOptions(), event.getSession() ); - } - - return new PersistenceContextEntry( old, EntityStatus.MANAGED ); - } - - /** - * see org.hibernate.event.internal.AbstractLockUpgradeEventListener#upgradeLock(Object, EntityEntry, LockOptions, EventSource) - */ - private static void upgradeLock(Object object, EntityEntry entry, LockOptions lockOptions, EventSource source) { - - LockMode requestedLockMode = lockOptions.getLockMode(); - if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) { - // The user requested a "greater" (i.e. more restrictive) form of pessimistic lock - - if ( entry.getStatus() != Status.MANAGED ) { - throw new ObjectDeletedException( - "attempted to lock a deleted instance", - entry.getId(), - entry.getPersister().getEntityName() - ); - } - - final EntityPersister persister = entry.getPersister(); - final boolean cachingEnabled = persister.canWriteToCache(); - SoftLock lock = null; - Object ck = null; - try { - if ( cachingEnabled ) { - EntityDataAccess cache = persister.getCacheAccessStrategy(); - ck = cache.generateCacheKey( entry.getId(), persister, source.getFactory(), source.getTenantIdentifier() ); - lock = cache.lockItem( source, ck, entry.getVersion() ); - } - - if ( persister.isVersioned() && requestedLockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT ) { - // todo : should we check the current isolation mode explicitly? - Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), source ); - entry.forceLocked( object, nextVersion ); - } - else { - ( (ReactiveEntityPersister) persister ) - .reactiveLock( entry.getId(), entry.getVersion(), object, lockOptions, source ); - } - entry.setLockMode( requestedLockMode ); - } - finally { - // the database now holds a lock + the object is flushed from the cache, - // so release the soft lock - if ( cachingEnabled ) { - persister.getCacheAccessStrategy().unlockItem( source, ck, lock ); - } - } - - } - } -} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractEntityPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractEntityPersister.java index a29799b23..c1015939c 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractEntityPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractEntityPersister.java @@ -39,13 +39,12 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.event.spi.EventSource; -import org.hibernate.event.spi.LoadEvent; import org.hibernate.generator.OnExecutionGenerator; import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.internal.util.collections.ArrayHelper; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.spi.NaturalIdLoader; +import org.hibernate.loader.ast.spi.SingleIdEntityLoader; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMappingsList; @@ -222,7 +221,7 @@ default CompletionStage reactiveLock( offset++; } getIdentifierType().nullSafeSet( statement, id, offset, session ); - offset += getIdentifierType().getColumnSpan( getFactory() ); + offset += getIdentifierType().getColumnSpan( getFactory().getRuntimeMetamodels() ); if ( isVersioned() ) { getVersionType().nullSafeSet( statement, version, offset, session ); } @@ -521,26 +520,19 @@ private CompletionStage loadFromDatabaseOrCache( EntityKey entityKey, Object identifier) { - // note that stateless sessions don't interact with second-level cache - if ( session instanceof EventSource && canReadFromCache() ) { - Object cached = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - new LoadEvent( identifier, entity, (EventSource) session, false ), - this, - entityKey - ); - if ( cached != null ) { - return completedFuture( cached ); + if ( canReadFromCache() && session.isEventSource() ) { + final EventSource eventSource = (EventSource) session; + Object loaded = eventSource.loadFromSecondLevelCache( this, entityKey, entity, LockMode.NONE ); + if ( loaded != null ) { + return completedFuture( loaded ); } } - - return getReactiveSingleIdEntityLoader().load( - identifier, - entity, - LockOptions.NONE, - session - ); + return ( (ReactiveSingleIdEntityLoader) determineLoaderToUse( session ) ) + .load( identifier, entity, LockOptions.NONE, session ); } + SingleIdEntityLoader determineLoaderToUse(SharedSessionContractImplementor session); + boolean initializeLazyProperty(String fieldName, Object entity, EntityEntry entry, int lazyIndex, Object selectedValue); Object initializeLazyProperty(String fieldName, Object entity, SharedSessionContractImplementor session); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveJoinedSubclassEntityPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveJoinedSubclassEntityPersister.java index 0de5391f0..c4e688ce6 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveJoinedSubclassEntityPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveJoinedSubclassEntityPersister.java @@ -139,6 +139,11 @@ protected AttributeMapping buildPluralAttributeMapping( ); } + @Override + public SingleIdEntityLoader determineLoaderToUse(SharedSessionContractImplementor session) { + return super.determineLoaderToUse( session ); + } + @Override protected InsertCoordinator buildInsertCoordinator() { return ReactiveCoordinatorFactory.buildInsertCoordinator( this, getFactory() ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveSingleTableEntityPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveSingleTableEntityPersister.java index bc52a7b6e..72b8c040e 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveSingleTableEntityPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveSingleTableEntityPersister.java @@ -86,6 +86,11 @@ public GeneratedValuesMutationDelegate createInsertDelegate() { return ReactiveAbstractEntityPersister.super.createReactiveInsertDelegate(); } + @Override + public SingleIdEntityLoader determineLoaderToUse(SharedSessionContractImplementor session) { + return super.determineLoaderToUse( session ); + } + @Override protected GeneratedValuesMutationDelegate createUpdateDelegate() { return ReactiveAbstractEntityPersister.super.createReactiveUpdateDelegate(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveUnionSubclassEntityPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveUnionSubclassEntityPersister.java index 420200027..c844f7644 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveUnionSubclassEntityPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveUnionSubclassEntityPersister.java @@ -139,6 +139,11 @@ protected AttributeMapping buildPluralAttributeMapping( ); } + @Override + public SingleIdEntityLoader determineLoaderToUse(SharedSessionContractImplementor session) { + return super.determineLoaderToUse( session ); + } + @Override public NaturalIdMapping generateNaturalIdMapping(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { return ReactiveAbstractEntityPersister.super.generateNaturalIdMapping(creationProcess, bootEntityDescriptor); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveIntegrator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveIntegrator.java index 0d1876320..5607d5935 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveIntegrator.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveIntegrator.java @@ -25,7 +25,6 @@ import org.hibernate.reactive.event.impl.DefaultReactivePersistOnFlushEventListener; import org.hibernate.reactive.event.impl.DefaultReactivePostLoadEventListener; import org.hibernate.reactive.event.impl.DefaultReactiveRefreshEventListener; -import org.hibernate.reactive.event.impl.DefaultReactiveResolveNaturalIdEventListener; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.service.ServiceRegistry; @@ -70,7 +69,6 @@ private void attachEventContextManagingListenersIfRequired(ServiceRegistry servi eventListenerRegistry.getEventListenerGroup( EventType.LOAD ).appendListener( new DefaultReactiveLoadEventListener() ); eventListenerRegistry.getEventListenerGroup( EventType.INIT_COLLECTION ).appendListener( new DefaultReactiveInitializeCollectionEventListener() ); eventListenerRegistry.getEventListenerGroup( EventType.POST_LOAD ).appendListener( new DefaultReactivePostLoadEventListener() ); - eventListenerRegistry.getEventListenerGroup( EventType.RESOLVE_NATURAL_ID ).appendListener( new DefaultReactiveResolveNaturalIdEventListener() ); } } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/internal/ReactiveNamedObjectRepositoryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/internal/ReactiveNamedObjectRepositoryImpl.java index 2ac40168c..ef2d70afe 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/internal/ReactiveNamedObjectRepositoryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/internal/ReactiveNamedObjectRepositoryImpl.java @@ -22,6 +22,7 @@ import org.hibernate.reactive.query.sql.spi.ReactiveNamedNativeQueryMemento; import org.hibernate.reactive.query.sql.spi.ReactiveNamedSqmQueryMemento; +import jakarta.persistence.Query; import jakarta.persistence.TypedQueryReference; public class ReactiveNamedObjectRepositoryImpl implements NamedObjectRepository { @@ -42,6 +43,11 @@ public NamedSqmQueryMemento getSqmQueryMemento(String queryName) { return wrapSqmQueryMemento( delegate.getSqmQueryMemento( queryName ) ); } + @Override + public void registerNamedQuery(String name, Query query) { + delegate.registerNamedQuery( name, query ); + } + @Override public void visitSqmQueryMementos(Consumer> action) { delegate.visitSqmQueryMementos( action ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ConcreteSqmSelectReactiveQueryPlan.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ConcreteSqmSelectReactiveQueryPlan.java index 01ee41c90..7c7cfd062 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ConcreteSqmSelectReactiveQueryPlan.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ConcreteSqmSelectReactiveQueryPlan.java @@ -261,7 +261,7 @@ private static CacheableSqmInterpretation buildCacheableSqmInterpretation( domainParameterXref, executionContext.getQueryParameterBindings(), executionContext.getSession().getLoadQueryInfluencers(), - sessionFactory, + sessionFactory.getSqlTranslationEngine(), true ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleDeleteQueryPlan.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleDeleteQueryPlan.java index 43271d29e..a17d1eb73 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleDeleteQueryPlan.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleDeleteQueryPlan.java @@ -82,7 +82,7 @@ protected SqlAstTranslator createTranslato domainParameterXref, executionContext.getQueryParameterBindings(), executionContext.getSession().getLoadQueryInfluencers(), - factory + factory.getSqlTranslationEngine() ); sqmInterpretation = (SqmTranslation) translator.translate(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleInsertQueryPlan.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleInsertQueryPlan.java index 9d76895b7..bf67d16ea 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleInsertQueryPlan.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleInsertQueryPlan.java @@ -102,7 +102,7 @@ private SqlAstTranslator createInsertTrans domainParameterXref, executionContext.getQueryParameterBindings(), executionContext.getSession().getLoadQueryInfluencers(), - factory + factory.getSqlTranslationEngine() ) .translate(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleUpdateQueryPlan.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleUpdateQueryPlan.java index 962149b5b..f49f848f5 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleUpdateQueryPlan.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSimpleUpdateQueryPlan.java @@ -103,7 +103,7 @@ private SqlAstTranslator createUpdateTrans domainParameterXref, executionContext.getQueryParameterBindings(), executionContext.getSession().getLoadQueryInfluencers(), - factory + factory.getSqlTranslationEngine() ); final SqmTranslation sqmInterpretation = translator.translate(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveAbstractCteMutationHandler.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveAbstractCteMutationHandler.java index 74f278fe7..20d0e31c5 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveAbstractCteMutationHandler.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveAbstractCteMutationHandler.java @@ -96,7 +96,7 @@ default CompletionStage reactiveExecute(DomainQueryExecutionContext exe executionContext.getQueryOptions(), executionContext.getSession().getLoadQueryInfluencers(), executionContext.getQueryParameterBindings(), - factory + factory.getSqlTranslationEngine() ); final Map, List> parameterResolutions; if ( getDomainParameterXref().getSqmParameterCount() == 0 ) { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveCteInsertHandler.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveCteInsertHandler.java index 5a4b1c5af..1e063f287 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveCteInsertHandler.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/cte/ReactiveCteInsertHandler.java @@ -83,12 +83,15 @@ public class ReactiveCteInsertHandler extends CteInsertHandler implements Reacti private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + private final SessionFactoryImplementor sessionFactory; + public ReactiveCteInsertHandler( CteTable cteTable, SqmInsertStatement sqmStatement, DomainParameterXref domainParameterXref, SessionFactoryImplementor sessionFactory) { super( cteTable, sqmStatement, domainParameterXref, sessionFactory ); + this.sessionFactory = sessionFactory; } @Override @@ -120,7 +123,7 @@ public CompletionStage reactiveExecute(DomainQueryExecutionContext exec executionContext.getQueryOptions(), executionContext.getSession().getLoadQueryInfluencers(), executionContext.getQueryParameterBindings(), - factory + factory.getSqlTranslationEngine() ); final TableGroup insertingTableGroup = sqmConverter.getMutatingTableGroup(); @@ -182,7 +185,7 @@ public CompletionStage reactiveExecute(DomainQueryExecutionContext exec querySpec -> { // This returns true if the insertion target uses a sequence with an optimizer // in which case we will fill the row_number column instead of the id column - if ( additionalInsertValues.applySelections( querySpec, getSessionFactory() ) ) { + if ( additionalInsertValues.applySelections( querySpec, sessionFactory ) ) { final CteColumn rowNumberColumn = getCteTable().getCteColumns() .get( getCteTable().getCteColumns().size() - 1 ); final ColumnReference columnReference = new ColumnReference( @@ -207,7 +210,7 @@ public CompletionStage reactiveExecute(DomainQueryExecutionContext exec 0, SqmInsertStrategyHelper.createRowNumberingExpression( querySpec, - getSessionFactory() + sessionFactory ) ) ); @@ -342,7 +345,7 @@ public CompletionStage reactiveExecute(DomainQueryExecutionContext exec ); final String fragment = ( (BulkInsertionCapableIdentifierGenerator) entityDescriptor.getGenerator() ) .determineBulkInsertionIdentifierGenerationSelectFragment( - getSessionFactory().getSqlStringGenerationContext() + sessionFactory.getSqlStringGenerationContext() ); rowsWithSequenceQuery.getSelectClause().addSqlSelection( new SqlSelectionImpl( diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/temptable/ReactiveRestrictedDeleteExecutionDelegate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/temptable/ReactiveRestrictedDeleteExecutionDelegate.java index dc2a833c4..0e1097b63 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/temptable/ReactiveRestrictedDeleteExecutionDelegate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/mutation/internal/temptable/ReactiveRestrictedDeleteExecutionDelegate.java @@ -117,7 +117,7 @@ public ReactiveRestrictedDeleteExecutionDelegate( queryOptions, loadQueryInfluencers, queryParameterBindings, - sessionFactory + sessionFactory.getSqlTranslationEngine() ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionImpl.java index f81eab1f9..87aaeb060 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionImpl.java @@ -28,7 +28,7 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.dialect.Dialect; -import org.hibernate.engine.internal.StatefulPersistenceContext; +import org.hibernate.engine.internal.ReactivePersistenceContextAdapter; import org.hibernate.engine.spi.EffectiveEntityGraph; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; @@ -55,7 +55,6 @@ import org.hibernate.event.spi.PersistEvent; import org.hibernate.event.spi.RefreshContext; import org.hibernate.event.spi.RefreshEvent; -import org.hibernate.event.spi.ResolveNaturalIdEvent; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; import org.hibernate.graph.spi.RootGraphImplementor; @@ -63,7 +62,11 @@ import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.SessionImpl; import org.hibernate.jpa.spi.NativeQueryTupleTransformer; +import org.hibernate.loader.LoaderLogging; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.internal.LoadAccessContext; +import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.HibernateProxy; @@ -87,7 +90,6 @@ import org.hibernate.reactive.common.InternalStateAssertions; import org.hibernate.reactive.common.ResultSetMapping; import org.hibernate.reactive.engine.ReactiveActionQueue; -import org.hibernate.reactive.engine.impl.ReactivePersistenceContextAdapter; import org.hibernate.reactive.event.ReactiveDeleteEventListener; import org.hibernate.reactive.event.ReactiveFlushEventListener; import org.hibernate.reactive.event.ReactiveLoadEventListener; @@ -95,9 +97,9 @@ import org.hibernate.reactive.event.ReactiveMergeEventListener; import org.hibernate.reactive.event.ReactivePersistEventListener; import org.hibernate.reactive.event.ReactiveRefreshEventListener; -import org.hibernate.reactive.event.ReactiveResolveNaturalIdEventListener; import org.hibernate.reactive.event.impl.DefaultReactiveAutoFlushEventListener; import org.hibernate.reactive.event.impl.DefaultReactiveInitializeCollectionEventListener; +import org.hibernate.reactive.loader.ast.spi.ReactiveNaturalIdLoader; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; @@ -186,8 +188,8 @@ private void threadCheck() { } @Override - protected StatefulPersistenceContext createPersistenceContext() { - return new ReactivePersistenceContextAdapter( this ); + protected PersistenceContext createPersistenceContext() { + return new ReactivePersistenceContextAdapter( super.createPersistenceContext() ); } @Override @@ -691,7 +693,7 @@ public CompletionStage reactiveInitializeCollection(PersistentCollection eventListenerGroupInitCollection = fastSessionServices.eventListenerGroup_INIT_COLLECTION; + EventListenerGroup eventListenerGroupInitCollection = getFactory().getEventListenerGroups().eventListenerGroup_INIT_COLLECTION; return eventListenerGroupInitCollection .fireEventOnEachListener( event, @@ -732,7 +734,7 @@ private CompletionStage firePersist(PersistEvent event) { checkTransactionSynchStatus(); checkNoUnresolvedActionsBeforeOperation(); - return fastSessionServices.eventListenerGroup_PERSIST + return getFactory().getEventListenerGroups().eventListenerGroup_PERSIST .fireEventOnEachListener( event, (ReactivePersistEventListener l) -> l::reactiveOnPersist ) .handle( (v, e) -> { checkNoUnresolvedActionsAfterOperation(); @@ -750,7 +752,7 @@ else if ( e instanceof RuntimeException ) { private CompletionStage firePersist(PersistContext copiedAlready, PersistEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_PERSIST + return getFactory().getEventListenerGroups().eventListenerGroup_PERSIST .fireEventOnEachListener( event, copiedAlready, (ReactivePersistEventListener l) -> l::reactiveOnPersist ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -774,7 +776,7 @@ public CompletionStage reactivePersistOnFlush(Object entity, PersistContex private CompletionStage firePersistOnFlush(PersistContext copiedAlready, PersistEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_PERSIST + return getFactory().getEventListenerGroups().eventListenerGroup_PERSIST .fireEventOnEachListener( event, copiedAlready, (ReactivePersistEventListener l) -> l::reactiveOnPersist ) .whenComplete( (v, e) -> delayedAfterCompletion() ); } @@ -802,13 +804,13 @@ public CompletionStage reactiveRemove( boolean isCascadeDeleteEnabled, DeleteContext transientEntities) { checkOpenOrWaitingForAutoClose(); - final boolean removingOrphanBeforeUpates = persistenceContext().isRemovingOrphanBeforeUpates(); - if ( LOG.isTraceEnabled() && removingOrphanBeforeUpates ) { + final boolean removingOrphanBeforeUpdates = persistenceContext().isRemovingOrphanBeforeUpdates(); + if ( LOG.isTraceEnabled() && removingOrphanBeforeUpdates ) { logRemoveOrphanBeforeUpdates( "before continuing", entityName, entityName ); } return fireRemove( - new DeleteEvent( entityName, child, isCascadeDeleteEnabled, removingOrphanBeforeUpates, this ), + new DeleteEvent( entityName, child, isCascadeDeleteEnabled, removingOrphanBeforeUpdates, this ), transientEntities ); } @@ -830,10 +832,8 @@ private void logRemoveOrphanBeforeUpdates(String timing, String entityName, Obje private CompletionStage fireRemove(DeleteEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_DELETE.fireEventOnEachListener( - event, - (ReactiveDeleteEventListener l) -> l::reactiveOnDelete - ) + return getFactory().getEventListenerGroups().eventListenerGroup_DELETE + .fireEventOnEachListener( event, (ReactiveDeleteEventListener l) -> l::reactiveOnDelete ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -854,9 +854,8 @@ else if ( e instanceof RuntimeException ) { private CompletionStage fireRemove(DeleteEvent event, DeleteContext transientEntities) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_DELETE.fireEventOnEachListener( event, transientEntities, - (ReactiveDeleteEventListener l) -> l::reactiveOnDelete - ) + return getFactory().getEventListenerGroups().eventListenerGroup_DELETE + .fireEventOnEachListener( event, transientEntities, (ReactiveDeleteEventListener l) -> l::reactiveOnDelete ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -892,7 +891,7 @@ private CompletionStage fireMerge(MergeEvent event) { checkTransactionSynchStatus(); checkNoUnresolvedActionsBeforeOperation(); - return fastSessionServices.eventListenerGroup_MERGE + return getFactory().getEventListenerGroups().eventListenerGroup_MERGE .fireEventOnEachListener( event, (ReactiveMergeEventListener l) -> l::reactiveOnMerge ) .handle( (v, e) -> { checkNoUnresolvedActionsAfterOperation(); @@ -914,7 +913,7 @@ else if ( e instanceof RuntimeException ) { private CompletionStage fireMerge(MergeContext copiedAlready, MergeEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_MERGE + return getFactory().getEventListenerGroups().eventListenerGroup_MERGE .fireEventOnEachListener( event, copiedAlready,(ReactiveMergeEventListener l) -> l::reactiveOnMerge ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -954,7 +953,7 @@ public CompletionStage reactiveAutoFlushIfRequired(Set querySpa // } AutoFlushEvent event = new AutoFlushEvent( querySpaces, this ); - return fastSessionServices.eventListenerGroup_AUTO_FLUSH + return getFactory().getEventListenerGroups().eventListenerGroup_AUTO_FLUSH .fireEventOnEachListener( event, (DefaultReactiveAutoFlushEventListener l) -> l::reactiveOnAutoFlush ) .thenApply( v -> event.isFlushRequired() ); } @@ -987,7 +986,7 @@ private CompletionStage doFlush() { throw LOG.flushDuringCascadeIsDangerous(); } - return fastSessionServices.eventListenerGroup_FLUSH + return getFactory().getEventListenerGroups().eventListenerGroup_FLUSH .fireEventOnEachListener( new FlushEvent( this ), (ReactiveFlushEventListener l) -> l::reactiveOnFlush ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -1036,10 +1035,8 @@ CompletionStage fireRefresh(RefreshEvent event) { } pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_REFRESH.fireEventOnEachListener( - event, - (ReactiveRefreshEventListener l) -> l::reactiveOnRefresh - ) + return getFactory().getEventListenerGroups().eventListenerGroup_REFRESH + .fireEventOnEachListener( event, (ReactiveRefreshEventListener l) -> l::reactiveOnRefresh ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -1059,12 +1056,8 @@ CompletionStage fireRefresh(RefreshEvent event) { private CompletionStage fireRefresh(RefreshContext refreshedAlready, RefreshEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_REFRESH - .fireEventOnEachListener( - event, - refreshedAlready, - (ReactiveRefreshEventListener l) -> l::reactiveOnRefresh - ) + return getFactory().getEventListenerGroups().eventListenerGroup_REFRESH + .fireEventOnEachListener( event, refreshedAlready, (ReactiveRefreshEventListener l) -> l::reactiveOnRefresh ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -1084,10 +1077,8 @@ public CompletionStage reactiveLock(Object object, LockOptions lockOptions private CompletionStage fireLock(LockEvent event) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_LOCK.fireEventOnEachListener( - event, - (ReactiveLockEventListener l) -> l::reactiveOnLock - ) + return getFactory().getEventListenerGroups().eventListenerGroup_LOCK + .fireEventOnEachListener( event, (ReactiveLockEventListener l) -> l::reactiveOnLock ) .handle( (v, e) -> { delayedAfterCompletion(); @@ -1175,11 +1166,21 @@ public CompletionStage> reactiveFind(Class entityClass, Object... @Override public CompletionStage reactiveFind(Class entityClass, Map ids) { - final EntityPersister persister = getFactory().getMappingMetamodel().getEntityDescriptor( entityClass ); - return new NaturalIdLoadAccessImpl( persister ).resolveNaturalId( ids ) + final ReactiveEntityPersister persister = entityPersister( entityClass ); + final Object normalizedIdValues = persister.getNaturalIdMapping().normalizeInput( ids ); + return new NaturalIdLoadAccessImpl( this, persister, requireEntityPersister( entityClass ) ) + .resolveNaturalId( normalizedIdValues ) .thenCompose( id -> reactiveFind( entityClass, id, null, null ) ); } + private ReactiveEntityPersister entityPersister(Class entityClass) { + return (ReactiveEntityPersister) getFactory().getMappingMetamodel().getEntityDescriptor( entityClass ); + } + + private EntityPersister requireEntityPersister(Class entityClass) { + return getFactory().getMappingMetamodel().getEntityDescriptor( entityClass ); + } + private CompletionStage fireReactiveLoad(LoadEvent event, LoadEventListener.LoadType loadType) { checkOpenOrWaitingForAutoClose(); @@ -1190,20 +1191,11 @@ private CompletionStage fireReactiveLoad(LoadEvent event, LoadEventListene private CompletionStage fireLoadNoChecks(LoadEvent event, LoadEventListener.LoadType loadType) { pulseTransactionCoordinator(); - return fastSessionServices.eventListenerGroup_LOAD + return getFactory().getEventListenerGroups().eventListenerGroup_LOAD .fireEventOnEachListener( event, loadType,(ReactiveLoadEventListener l) -> l::reactiveOnLoad ); } - private CompletionStage fireResolveNaturalId(ResolveNaturalIdEvent event) { - checkOpenOrWaitingForAutoClose(); - return fastSessionServices.eventListenerGroup_RESOLVE_NATURAL_ID.fireEventOnEachListener( - event, - (ReactiveResolveNaturalIdEventListener l) -> l::onReactiveResolveNaturalId - ) - .whenComplete( (c, e) -> delayedAfterCompletion() ); - } - @Override public void delayedAfterCompletion() { //disable for now, but figure out what to do here @@ -1472,8 +1464,7 @@ public CompletionStage> multiLoad(Object... ids) { Object[] sids = new Object[ids.length]; System.arraycopy( ids, 0, sids, 0, ids.length ); - return perform( () -> (CompletionStage) - ( (ReactiveEntityPersister) entityPersister ) + return perform( () -> (CompletionStage) ( (ReactiveEntityPersister) entityPersister ) .reactiveMultiLoad( sids, ReactiveSessionImpl.this, this ) ); } @@ -1517,12 +1508,16 @@ public CompletionStage> multiLoad(List ids) { } private class NaturalIdLoadAccessImpl { - private final EntityPersister entityPersister; + private final LoadAccessContext context; + private final ReactiveEntityPersister entityPersister; + private final EntityMappingType entityDescriptor; private LockOptions lockOptions; private boolean synchronizationEnabled = true; - private NaturalIdLoadAccessImpl(EntityPersister entityPersister) { + private NaturalIdLoadAccessImpl(LoadAccessContext context, ReactiveEntityPersister entityPersister, EntityMappingType entityDescriptor) { + this.context = context; this.entityPersister = entityPersister; + this.entityDescriptor = entityDescriptor; if ( !entityPersister.hasNaturalIdentifier() ) { throw LOG.entityDidNotDefinedNaturalId( entityPersister.getEntityName() ); @@ -1538,13 +1533,35 @@ protected void synchronizationEnabled(boolean synchronizationEnabled) { this.synchronizationEnabled = synchronizationEnabled; } - protected final CompletionStage resolveNaturalId(Map naturalIdParameters) { + /** + * @see org.hibernate.loader.internal.BaseNaturalIdLoadAccessImpl#doGetReference(Object) + */ + protected final CompletionStage resolveNaturalId(Object normalizedNaturalIdValue) { performAnyNeededCrossReferenceSynchronizations(); - ResolveNaturalIdEvent event = - new ResolveNaturalIdEvent( naturalIdParameters, entityPersister, ReactiveSessionImpl.this ); - return fireResolveNaturalId( event ) - .thenApply( v -> event.getEntityId() == INVALID_NATURAL_ID_REFERENCE ? null : event.getEntityId() ); + context.checkOpenOrWaitingForAutoClose(); + context.pulseTransactionCoordinator(); + + final SessionImplementor session = getSession(); + final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final Object cachedResolution = persistenceContext.getNaturalIdResolutions() + .findCachedIdByNaturalId( normalizedNaturalIdValue, entityPersister() ); + if ( cachedResolution == INVALID_NATURAL_ID_REFERENCE ) { + // the entity is deleted, although not yet flushed - return null + return nullFuture(); + } + else if ( cachedResolution != null ) { + return completedFuture( cachedResolution ); + } + else { + LoaderLogging.LOADER_LOGGER.debugf( + "Selecting entity identifier by natural-id for `#getReference` handling - %s : %s", + entityPersister().getEntityName(), + normalizedNaturalIdValue + ); + return ( (ReactiveNaturalIdLoader) entityPersister().getNaturalIdLoader() ) + .resolveNaturalIdToId( normalizedNaturalIdValue, session ); + } } protected void performAnyNeededCrossReferenceSynchronizations() { @@ -1552,7 +1569,9 @@ protected void performAnyNeededCrossReferenceSynchronizations() { // synchronization (this process) was disabled return; } - if ( entityPersister.getEntityMetamodel().hasImmutableNaturalId() ) { + + final NaturalIdMapping naturalIdMapping = entityDescriptor.getNaturalIdMapping(); + if ( !naturalIdMapping.isMutable() ) { // only mutable natural-ids need this processing return; } @@ -1562,7 +1581,7 @@ protected void performAnyNeededCrossReferenceSynchronizations() { } final PersistenceContext persistenceContext = getPersistenceContextInternal(); -// final boolean debugEnabled = log.isDebugEnabled(); + final boolean loggerDebugEnabled = LoaderLogging.LOADER_LOGGER.isDebugEnabled(); for ( Object pk : persistenceContext.getNaturalIdResolutions() .getCachedPkResolutions( entityPersister ) ) { final EntityKey entityKey = generateEntityKey( pk, entityPersister ); @@ -1570,12 +1589,13 @@ protected void performAnyNeededCrossReferenceSynchronizations() { final EntityEntry entry = persistenceContext.getEntry( entity ); if ( entry == null ) { -// if ( debugEnabled ) { -// log.debug( -// "Cached natural-id/pk resolution linked to null EntityEntry in persistence context : " -// + MessageHelper.infoString( entityPersister, pk, getFactory() ) -// ); -// } + if ( loggerDebugEnabled ) { + LoaderLogging.LOADER_LOGGER.debugf( + "Cached natural-id/pk resolution linked to null EntityEntry in persistence context : %s#%s", + entityDescriptor.getEntityName(), + pk + ); + } continue; } @@ -1588,21 +1608,19 @@ protected void performAnyNeededCrossReferenceSynchronizations() { continue; } - persistenceContext.getNaturalIdResolutions() - .handleSynchronization( pk, entity, entityPersister ); + persistenceContext.getNaturalIdResolutions().handleSynchronization( pk, entity, entityPersister() ); } } protected final ReactiveIdentifierLoadAccessImpl getIdentifierLoadAccess() { - final ReactiveIdentifierLoadAccessImpl identifierLoadAccess = new ReactiveIdentifierLoadAccessImpl<>( - entityPersister ); + final ReactiveIdentifierLoadAccessImpl identifierLoadAccess = new ReactiveIdentifierLoadAccessImpl<>( entityPersister ); if ( this.lockOptions != null ) { identifierLoadAccess.with( lockOptions ); } return identifierLoadAccess; } - protected EntityPersister entityPersister() { + protected ReactiveEntityPersister entityPersister() { return entityPersister; } } @@ -1688,7 +1706,7 @@ public void removeOrphanBeforeUpdates(String entityName, Object child) { public CompletionStage reactiveRemoveOrphanBeforeUpdates(String entityName, Object child) { // TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. This should be removed once action/task // ordering is improved. - final StatefulPersistenceContext persistenceContext = (StatefulPersistenceContext) getPersistenceContextInternal(); + final PersistenceContext persistenceContext = getPersistenceContextInternal(); persistenceContext.beginRemoveOrphanBeforeUpdates(); return fireRemove( new DeleteEvent( entityName, child, false, true, this ) ) .thenAccept( v -> { @@ -1709,7 +1727,7 @@ private void logRemoveOrphanBeforeUpdates( String timing, String entityName, Object entity, - StatefulPersistenceContext persistenceContext) { + PersistenceContext persistenceContext) { if ( LOG.isTraceEnabled() ) { final EntityEntry entityEntry = persistenceContext.getEntry( entity ); LOG.tracef( diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveStatelessSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveStatelessSessionImpl.java index 2e9dd3df1..230c4a5fb 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveStatelessSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveStatelessSessionImpl.java @@ -62,7 +62,7 @@ import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; import org.hibernate.reactive.common.AffectedEntities; import org.hibernate.reactive.common.ResultSetMapping; -import org.hibernate.reactive.engine.impl.ReactivePersistenceContextAdapter; +import org.hibernate.engine.internal.ReactivePersistenceContextAdapter; import org.hibernate.reactive.id.ReactiveIdentifierGenerator; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.persister.collection.impl.ReactiveCollectionPersister; @@ -133,7 +133,7 @@ public class ReactiveStatelessSessionImpl extends StatelessSessionImpl implement public ReactiveStatelessSessionImpl(SessionFactoryImpl factory, SessionCreationOptions options, ReactiveConnection connection) { super( factory, options ); reactiveConnection = connection; - persistenceContext = new ReactivePersistenceContextAdapter( this ); + persistenceContext = new ReactivePersistenceContextAdapter( super.getPersistenceContext() ); batchingHelperSession = new ReactiveStatelessSessionImpl( factory, options, reactiveConnection, persistenceContext ); influencers = new LoadQueryInfluencers( factory ); } @@ -315,13 +315,13 @@ private CompletionStage reactiveInsert(Object entity, ReactiveEntityPersis } private boolean firePreInsert(Object entity, Object id, Object[] state, EntityPersister persister) { - if ( fastSessionServices.eventListenerGroup_PRE_INSERT.isEmpty() ) { + if ( getFactory().getEventListenerGroups().eventListenerGroup_PRE_INSERT.isEmpty() ) { return false; } else { boolean veto = false; final PreInsertEvent event = new PreInsertEvent( entity, id, state, persister, null ); - for ( PreInsertEventListener listener : fastSessionServices.eventListenerGroup_PRE_INSERT.listeners() ) { + for ( PreInsertEventListener listener : getFactory().getEventListenerGroups().eventListenerGroup_PRE_INSERT.listeners() ) { veto |= listener.onPreInsert( event ); } return veto; @@ -329,9 +329,9 @@ private boolean firePreInsert(Object entity, Object id, Object[] state, EntityPe } private void firePostInsert(Object entity, Object id, Object[] state, EntityPersister persister) { - if ( !fastSessionServices.eventListenerGroup_POST_INSERT.isEmpty() ) { + if ( !getFactory().getEventListenerGroups().eventListenerGroup_POST_INSERT.isEmpty() ) { final PostInsertEvent event = new PostInsertEvent( entity, id, state, persister, null ); - for ( PostInsertEventListener listener : fastSessionServices.eventListenerGroup_POST_INSERT.listeners() ) { + for ( PostInsertEventListener listener : getFactory().getEventListenerGroups().eventListenerGroup_POST_INSERT.listeners() ) { listener.onPostInsert( event ); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/StandardReactiveSelectExecutor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/StandardReactiveSelectExecutor.java index bcf33c942..43b7c1554 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/StandardReactiveSelectExecutor.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/StandardReactiveSelectExecutor.java @@ -19,7 +19,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.query.TupleTransformer; -import org.hibernate.reactive.engine.impl.ReactivePersistenceContextAdapter; +import org.hibernate.engine.internal.ReactivePersistenceContextAdapter; import org.hibernate.reactive.sql.exec.spi.ReactiveRowProcessingState; import org.hibernate.reactive.sql.exec.spi.ReactiveSelectExecutor; import org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet; diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityDelayedFetchInitializer.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityDelayedFetchInitializer.java index 1a1660725..c40ee20d3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityDelayedFetchInitializer.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityDelayedFetchInitializer.java @@ -131,7 +131,7 @@ public CompletionStage reactiveResolveInstance(EntityDelayedFetchInitializ final String uniqueKeyPropertyName = referencedModelPart.getReferencedPropertyName(); final Type uniqueKeyPropertyType = uniqueKeyPropertyName == null ? concreteDescriptor.getIdentifierType() - : session.getFactory().getReferencedPropertyType( concreteDescriptor.getEntityName(), uniqueKeyPropertyName ); + : session.getFactory().getRuntimeMetamodels().getReferencedPropertyType( concreteDescriptor.getEntityName(), uniqueKeyPropertyName ); final EntityUniqueKey euk = new EntityUniqueKey( concreteDescriptor.getEntityName(), uniqueKeyPropertyName, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityInitializerImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityInitializerImpl.java index a00287eab..8601d434f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityInitializerImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntityInitializerImpl.java @@ -20,7 +20,6 @@ import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; -import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.LazyInitializer; @@ -45,6 +44,7 @@ import static org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer.UNFETCHED_PROPERTY; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; +import static org.hibernate.loader.internal.CacheLoadHelper.loadFromSecondLevelCache; import static org.hibernate.metamodel.mapping.ForeignKeyDescriptor.Nature.TARGET; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; @@ -576,7 +576,7 @@ private boolean isProxyInstance(Object proxy) { // FIXME: I could change the scope of this method in ORM private Object resolveInstanceFromCache(ReactiveEntityInitializerData data) { - return CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( + return loadFromSecondLevelCache( data.getRowProcessingState().getSession().asEventSource(), null, data.getLockMode(), diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveXmlJdbcType.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveXmlJdbcType.java index 1362e3a20..3c3667aa3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveXmlJdbcType.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveXmlJdbcType.java @@ -48,7 +48,7 @@ protected X fromString(String string, JavaType javaType, WrapperOptions o if ( javaType.getJavaType() == SQLXML.class ) { throw LOG.unsupportedXmlType(); } - return options.getSessionFactory().getFastSessionServices().getXmlFormatMapper() + return options.getSessionFactory().getSessionFactoryOptions().getXmlFormatMapper() .fromString( string, javaType, options ); }