From dac4d59c4fe956ef1ed95a06a115b13c27b7e8d9 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Wed, 30 Apr 2025 19:46:27 +0200 Subject: [PATCH 1/2] [#2238] create Delegators for use in Quarkus --- .../delegation/MutinySessionDelegator.java | 341 ++++++++++++++++++ .../MutinyStatelessSessionDelegator.java | 191 ++++++++++ .../delegation/ConcreteSessionDelegator.java | 17 + .../ConcreteStatelessSessionDelegator.java | 17 + 4 files changed, 566 insertions(+) create mode 100644 hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinySessionDelegator.java create mode 100644 hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinyStatelessSessionDelegator.java create mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteSessionDelegator.java create mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteStatelessSessionDelegator.java diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinySessionDelegator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinySessionDelegator.java new file mode 100644 index 000000000..09d85913a --- /dev/null +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinySessionDelegator.java @@ -0,0 +1,341 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.mutiny.delegation; + +import io.smallrye.mutiny.Uni; +import jakarta.persistence.CacheRetrieveMode; +import jakarta.persistence.CacheStoreMode; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.LockModeType; +import jakarta.persistence.criteria.CriteriaDelete; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.CriteriaUpdate; +import jakarta.persistence.metamodel.Attribute; +import org.hibernate.CacheMode; +import org.hibernate.Filter; +import org.hibernate.FlushMode; +import org.hibernate.Incubating; +import org.hibernate.LockMode; +import org.hibernate.reactive.common.AffectedEntities; +import org.hibernate.reactive.common.Identifier; +import org.hibernate.reactive.common.ResultSetMapping; +import org.hibernate.reactive.mutiny.Mutiny; + +import java.util.List; +import java.util.function.Function; + +/** + * Wraps a {@linkplain #delegate} session. + * + * @author Gavin King + */ +public abstract class MutinySessionDelegator implements Mutiny.Session { + + public abstract Mutiny.Session delegate(); + + public Uni find(Class entityClass, Object id) { + return delegate().find(entityClass, id); + } + + public Uni find(Class entityClass, Object id, LockModeType lockModeType) { + return delegate().find(entityClass, id, lockModeType); + } + + public Uni find(Class entityClass, Object id, LockMode lockMode) { + return delegate().find(entityClass, id, lockMode); + } + + public Uni find(EntityGraph entityGraph, Object id) { + return delegate().find(entityGraph, id); + } + + public Uni> find(Class entityClass, Object... ids) { + return delegate().find(entityClass, ids); + } + + public Mutiny.SelectionQuery createNamedQuery(String queryName, Class resultType) { + return delegate().createNamedQuery(queryName, resultType); + } + + public Mutiny.SelectionQuery createQuery(String queryString, Class resultType) { + return delegate().createQuery(queryString, resultType); + } + + public boolean isReadOnly(Object entityOrProxy) { + return delegate().isReadOnly(entityOrProxy); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, Class resultType, AffectedEntities affectedEntities) { + return delegate().createNativeQuery(queryString, resultType, affectedEntities); + } + + public boolean isDefaultReadOnly() { + return delegate().isDefaultReadOnly(); + } + + public Uni unproxy(T association) { + return delegate().unproxy(association); + } + + public Mutiny.MutationQuery createMutationQuery(String queryString) { + return delegate().createMutationQuery(queryString); + } + + public Uni close() { + return delegate().close(); + } + + public Mutiny.Session disableFetchProfile(String name) { + return delegate().disableFetchProfile(name); + } + + public EntityGraph getEntityGraph(Class rootType, String graphName) { + return delegate().getEntityGraph(rootType, graphName); + } + + public Mutiny.SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return delegate().createSelectionQuery(queryString, resultType); + } + + public Uni refresh(Object entity, LockModeType lockModeType) { + return delegate().refresh(entity, lockModeType); + } + + public Uni lock(Object entity, LockModeType lockModeType) { + return delegate().lock(entity, lockModeType); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, ResultSetMapping resultSetMapping, AffectedEntities affectedEntities) { + return delegate().createNativeQuery(queryString, resultSetMapping, affectedEntities); + } + + public Uni lock(Object entity, LockMode lockMode) { + return delegate().lock(entity, lockMode); + } + + @Incubating + public Uni find(Class entityClass, Identifier naturalId) { + return delegate().find(entityClass, naturalId); + } + + public Uni withTransaction(Function> work) { + return delegate().withTransaction(work); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, ResultSetMapping resultSetMapping) { + return delegate().createNativeQuery(queryString, resultSetMapping); + } + + public EntityGraph createEntityGraph(Class rootType, String graphName) { + return delegate().createEntityGraph(rootType, graphName); + } + + public Mutiny.Transaction currentTransaction() { + return delegate().currentTransaction(); + } + + public Mutiny.Session detach(Object entity) { + return delegate().detach(entity); + } + + public Mutiny.Session setCacheStoreMode(CacheStoreMode cacheStoreMode) { + return delegate().setCacheStoreMode(cacheStoreMode); + } + + public FlushMode getFlushMode() { + return delegate().getFlushMode(); + } + + public LockMode getLockMode(Object entity) { + return delegate().getLockMode(entity); + } + + public Mutiny.Query createNamedQuery(String queryName) { + return delegate().createNamedQuery(queryName); + } + + public Mutiny.SessionFactory getFactory() { + return delegate().getFactory(); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, Class resultType) { + return delegate().createNativeQuery(queryString, resultType); + } + + public Mutiny.Session setSubselectFetchingEnabled(boolean enabled) { + return delegate().setSubselectFetchingEnabled(enabled); + } + + public Mutiny.Session setFlushMode(FlushMode flushMode) { + return delegate().setFlushMode(flushMode); + } + + public Uni remove(Object entity) { + return delegate().remove(entity); + } + + public Mutiny.Session setCacheMode(CacheMode cacheMode) { + return delegate().setCacheMode(cacheMode); + } + + public Filter enableFilter(String filterName) { + return delegate().enableFilter(filterName); + } + + public Mutiny.Query createNativeQuery(String queryString, AffectedEntities affectedEntities) { + return delegate().createNativeQuery(queryString, affectedEntities); + } + + public Mutiny.Session setReadOnly(Object entityOrProxy, boolean readOnly) { + return delegate().setReadOnly(entityOrProxy, readOnly); + } + + public EntityGraph createEntityGraph(Class rootType) { + return delegate().createEntityGraph(rootType); + } + + public Uni refreshAll(Object... entities) { + return delegate().refreshAll(entities); + } + + public Integer getBatchSize() { + return delegate().getBatchSize(); + } + + public Uni refresh(Object entity, LockMode lockMode) { + return delegate().refresh(entity, lockMode); + } + + public T getReference(Class entityClass, Object id) { + return delegate().getReference(entityClass, id); + } + + public T getReference(T entity) { + return delegate().getReference(entity); + } + + public Mutiny.Session setBatchSize(Integer batchSize) { + return delegate().setBatchSize(batchSize); + } + + public Uni refresh(Object entity) { + return delegate().refresh(entity); + } + + public CacheMode getCacheMode() { + return delegate().getCacheMode(); + } + + public Uni mergeAll(Object... entities) { + return delegate().mergeAll(entities); + } + + public Uni persist(Object object) { + return delegate().persist(object); + } + + public boolean contains(Object entity) { + return delegate().contains(entity); + } + + public int getFetchBatchSize() { + return delegate().getFetchBatchSize(); + } + + public Mutiny.Session setDefaultReadOnly(boolean readOnly) { + return delegate().setDefaultReadOnly(readOnly); + } + + public Mutiny.Session clear() { + return delegate().clear(); + } + + public Uni fetch(E entity, Attribute field) { + return delegate().fetch(entity, field); + } + + public Mutiny.SelectionQuery createQuery(CriteriaQuery criteriaQuery) { + return delegate().createQuery(criteriaQuery); + } + + public Mutiny.Session setCacheRetrieveMode(CacheRetrieveMode cacheRetrieveMode) { + return delegate().setCacheRetrieveMode(cacheRetrieveMode); + } + + public Uni removeAll(Object... entities) { + return delegate().removeAll(entities); + } + + public Filter getEnabledFilter(String filterName) { + return delegate().getEnabledFilter(filterName); + } + + public void disableFilter(String filterName) { + delegate().disableFilter(filterName); + } + + public Mutiny.MutationQuery createQuery(CriteriaDelete criteriaDelete) { + return delegate().createQuery(criteriaDelete); + } + + public Mutiny.Session enableFetchProfile(String name) { + return delegate().enableFetchProfile(name); + } + + public ResultSetMapping getResultSetMapping(Class resultType, String mappingName) { + return delegate().getResultSetMapping(resultType, mappingName); + } + + public Uni flush() { + return delegate().flush(); + } + + public Mutiny.Query createNativeQuery(String queryString) { + return delegate().createNativeQuery(queryString); + } + + public boolean isFetchProfileEnabled(String name) { + return delegate().isFetchProfileEnabled(name); + } + + public Uni merge(T entity) { + return delegate().merge(entity); + } + + public boolean isSubselectFetchingEnabled() { + return delegate().isSubselectFetchingEnabled(); + } + + public Mutiny.MutationQuery createQuery(CriteriaUpdate criteriaUpdate) { + return delegate().createQuery(criteriaUpdate); + } + + public Mutiny.Session setFetchBatchSize(int batchSize) { + return delegate().setFetchBatchSize(batchSize); + } + + public Uni fetch(T association) { + return delegate().fetch(association); + } + + public Uni persistAll(Object... entities) { + return delegate().persistAll(entities); + } + + @Deprecated + public Mutiny.Query createQuery(String queryString) { + return delegate().createQuery(queryString); + } + + public Mutiny.Session setFlushMode(FlushModeType flushModeType) { + return delegate().setFlushMode(flushModeType); + } + + public boolean isOpen() { + return delegate().isOpen(); + } +} diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinyStatelessSessionDelegator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinyStatelessSessionDelegator.java new file mode 100644 index 000000000..152140006 --- /dev/null +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/delegation/MutinyStatelessSessionDelegator.java @@ -0,0 +1,191 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.mutiny.delegation; + +import io.smallrye.mutiny.Uni; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.LockModeType; +import jakarta.persistence.criteria.CriteriaQuery; +import org.hibernate.Incubating; +import org.hibernate.LockMode; +import org.hibernate.reactive.common.ResultSetMapping; +import org.hibernate.reactive.mutiny.Mutiny; + +import java.util.function.Function; + +/** + * Wraps a {@linkplain #delegate} stateless session. + * + * @author Gavin King + */ +public abstract class MutinyStatelessSessionDelegator implements Mutiny.StatelessSession { + + public abstract Mutiny.StatelessSession delegate(); + + public Uni get(Class entityClass, Object id) { + return delegate().get(entityClass, id); + } + + @Deprecated + public Mutiny.Query createQuery(String queryString) { + return delegate().createQuery(queryString); + } + + public Uni get(EntityGraph entityGraph, Object id) { + return delegate().get(entityGraph, id); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, ResultSetMapping resultSetMapping) { + return delegate().createNativeQuery(queryString, resultSetMapping); + } + + public Uni get(Class entityClass, Object id, LockMode lockMode) { + return delegate().get(entityClass, id, lockMode); + } + + public boolean isOpen() { + return delegate().isOpen(); + } + + public Uni insertAll(Object... entities) { + return delegate().insertAll(entities); + } + + public Uni updateAll(int batchSize, Object... entities) { + return delegate().updateAll(batchSize, entities); + } + + public EntityGraph createEntityGraph(Class rootType, String graphName) { + return delegate().createEntityGraph(rootType, graphName); + } + + public EntityGraph getEntityGraph(Class rootType, String graphName) { + return delegate().getEntityGraph(rootType, graphName); + } + + public Uni get(Class entityClass, Object id, LockModeType lockModeType) { + return delegate().get(entityClass, id, lockModeType); + } + + public Uni update(Object entity) { + return delegate().update(entity); + } + + public Uni refreshAll(int batchSize, Object... entities) { + return delegate().refreshAll(batchSize, entities); + } + + public Mutiny.SelectionQuery createQuery(String queryString, Class resultType) { + return delegate().createQuery(queryString, resultType); + } + + public Uni delete(Object entity) { + return delegate().delete(entity); + } + + public Uni refresh(Object entity, LockModeType lockModeType) { + return delegate().refresh(entity, lockModeType); + } + + public Mutiny.SessionFactory getFactory() { + return delegate().getFactory(); + } + + public Mutiny.SelectionQuery createNativeQuery(String queryString, Class resultType) { + return delegate().createNativeQuery(queryString, resultType); + } + + public Uni deleteAll(Object... entities) { + return delegate().deleteAll(entities); + } + + public Mutiny.SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return delegate().createSelectionQuery(queryString, resultType); + } + + @Incubating + public Uni upsert(Object entity) { + return delegate().upsert(entity); + } + + public Mutiny.MutationQuery createMutationQuery(String queryString) { + return delegate().createMutationQuery(queryString); + } + + public Uni refresh(Object entity) { + return delegate().refresh(entity); + } + + public ResultSetMapping getResultSetMapping(Class resultType, String mappingName) { + return delegate().getResultSetMapping(resultType, mappingName); + } + + public Uni insertAll(int batchSize, Object... entities) { + return delegate().insertAll(batchSize, entities); + } + + public Mutiny.Query createNativeQuery(String queryString) { + return delegate().createNativeQuery(queryString); + } + + public Mutiny.Query createNamedQuery(String queryName) { + return delegate().createNamedQuery(queryName); + } + + public Mutiny.SelectionQuery createNamedQuery(String queryName, Class resultType) { + return delegate().createNamedQuery(queryName, resultType); + } + + public Uni refreshAll(Object... entities) { + return delegate().refreshAll(entities); + } + + public Uni close() { + return delegate().close(); + } + + public Uni updateAll(Object... entities) { + return delegate().updateAll(entities); + } + + public Mutiny.SelectionQuery createQuery(CriteriaQuery criteriaQuery) { + return delegate().createQuery(criteriaQuery); + } + + public Uni withTransaction(Function> work) { + return delegate().withTransaction(work); + } + + public Uni fetch(T association) { + return delegate().fetch(association); + } + + @Incubating + public Uni upsert(String entityName, Object entity) { + return delegate().upsert(entityName, entity); + } + + @Incubating + public Mutiny.Transaction currentTransaction() { + return delegate().currentTransaction(); + } + + public EntityGraph createEntityGraph(Class rootType) { + return delegate().createEntityGraph(rootType); + } + + public Uni insert(Object entity) { + return delegate().insert(entity); + } + + public Uni refresh(Object entity, LockMode lockMode) { + return delegate().refresh(entity, lockMode); + } + + public Uni deleteAll(int batchSize, Object... entities) { + return delegate().deleteAll(batchSize, entities); + } +} diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteSessionDelegator.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteSessionDelegator.java new file mode 100644 index 000000000..2c93d9226 --- /dev/null +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteSessionDelegator.java @@ -0,0 +1,17 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.delegation; + +import org.hibernate.reactive.mutiny.Mutiny; +import org.hibernate.reactive.mutiny.delegation.MutinySessionDelegator; + +@SuppressWarnings("unused") +class ConcreteSessionDelegator extends MutinySessionDelegator { + @Override + public Mutiny.Session delegate() { + throw new UnsupportedOperationException(); + } +} diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteStatelessSessionDelegator.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteStatelessSessionDelegator.java new file mode 100644 index 000000000..e275d0180 --- /dev/null +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/delegation/ConcreteStatelessSessionDelegator.java @@ -0,0 +1,17 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.delegation; + +import org.hibernate.reactive.mutiny.Mutiny; +import org.hibernate.reactive.mutiny.delegation.MutinyStatelessSessionDelegator; + +@SuppressWarnings("unused") +class ConcreteStatelessSessionDelegator extends MutinyStatelessSessionDelegator { + @Override + public Mutiny.StatelessSession delegate() { + throw new UnsupportedOperationException(); + } +} From ce183ff81b2eeab65742567f92f49cb403669bb5 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Wed, 30 Apr 2025 11:44:50 +0200 Subject: [PATCH 2/2] [#1780] add operations for obtaining the current sessions from the context this will make it easier to implement the necessary Quarkus integration --- .../org/hibernate/reactive/mutiny/Mutiny.java | 25 +++++++++++++++++++ .../mutiny/impl/MutinySessionFactoryImpl.java | 10 ++++++++ .../org/hibernate/reactive/stage/Stage.java | 25 +++++++++++++++++++ .../stage/impl/StageSessionFactoryImpl.java | 10 ++++++++ 4 files changed, 70 insertions(+) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java index 65b0ad906..90972f9c5 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/Mutiny.java @@ -2279,6 +2279,31 @@ default Uni withStatelessTransaction(Function> w */ Statistics getStatistics(); + /** + * Return the current instance of {@link Session}, if any. + * A current session exists only when this method is called + * from within an invocation of {@link #withSession(Function)} + * or {@link #withTransaction(Function)}. + * + * @return the current instance, if any, or {@code null} + * + * @since 2.4.7 + */ + Session getCurrentSession(); + + /** + * Return the current instance of {@link Session}, if any. + * A current session exists only when this method is called + * from within an invocation of + * {@link #withStatelessSession(Function)} or + * {@link #withStatelessTransaction(Function)}. + * + * @return the current instance, if any, or {@code null} + * + * @since 2.4.7 + */ + StatelessSession getCurrentStatelessSession(); + /** * Destroy the session factory and clean up its connection pool. */ diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java index aecc99e37..23feaba57 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionFactoryImpl.java @@ -148,6 +148,16 @@ private CompletionStage connection(String tenantId) { : connectionPool.getConnection( tenantId ); } + @Override + public Mutiny.Session getCurrentSession() { + return context.get( contextKeyForSession ); + } + + @Override + public Mutiny.StatelessSession getCurrentStatelessSession() { + return context.get( contextKeyForStatelessSession ); + } + @Override public Uni withSession(Function> work) { Objects.requireNonNull( work, "parameter 'work' is required" ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java index 47da9f6cf..3a6164a39 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/Stage.java @@ -2314,6 +2314,31 @@ default CompletionStage withStatelessTransaction(Function connection(String tenantId) { : connectionPool.getConnection( tenantId ); } + @Override + public Stage.Session getCurrentSession() { + return context.get( contextKeyForSession ); + } + + @Override + public Stage.StatelessSession getCurrentStatelessSession() { + return context.get( contextKeyForStatelessSession ); + } + @Override public CompletionStage withSession(Function> work) { Objects.requireNonNull( work, "parameter 'work' is required" );