From b44da8a8ff1d5df6807d4424fbdc91a0258fa9bf Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 4 Aug 2023 15:21:59 +0200 Subject: [PATCH 01/14] Set default Hibernate ORM to 6.3.CR1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fd98dc704..f82e94e5d 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,7 @@ version = projectVersion // ./gradlew clean build -PhibernateOrmVersion=5.6.15-SNAPSHOT ext { if ( !project.hasProperty('hibernateOrmVersion') ) { - hibernateOrmVersion = '6.2.7.Final' + hibernateOrmVersion = '6.3.0.CR1' } if ( !project.hasProperty( 'hibernateOrmGradlePluginVersion' ) ) { // Same as ORM as default From 0a62e276e92d6c7c7b0401938329719e544135c7 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 4 Aug 2023 15:22:28 +0200 Subject: [PATCH 02/14] Use latest snapshot from local repository --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4acfdfc65..a935d495a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,15 +32,15 @@ org.gradle.java.installations.auto-download=false #enableSonatypeOpenSourceSnapshotsRep = true # Enable the maven local repository (for local development when needed) when present (value ignored) -#enableMavenLocalRepo = true +enableMavenLocalRepo = true # Override default Hibernate ORM version -#hibernateOrmVersion = 6.2.3.Final +hibernateOrmVersion = 6.3.0-SNAPSHOT # 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 = 6.2.3.Final +hibernateOrmGradlePluginVersion = 6.3.0.CR1 # 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 From 941e628ab775ad0a6336c69072a47bc50f6cefdf Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 4 Aug 2023 15:23:41 +0200 Subject: [PATCH 03/14] Remove duplicated MutinyMain A mistake, this class is in the examples. --- .../reactive/example/MutinyMain.java | 414 ------------------ 1 file changed, 414 deletions(-) delete mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/example/MutinyMain.java diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/example/MutinyMain.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/example/MutinyMain.java deleted file mode 100644 index cb242e052..000000000 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/example/MutinyMain.java +++ /dev/null @@ -1,414 +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.example; - -import io.vertx.junit5.Timeout; -import io.vertx.junit5.VertxTestContext; -import jakarta.persistence.*; -import jakarta.persistence.criteria.*; -import org.hibernate.reactive.BaseReactiveTest; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; - -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import static jakarta.persistence.FetchType.LAZY; -import static java.lang.System.out; -import static java.time.Month.*; -import static java.util.concurrent.TimeUnit.MINUTES; - -@Timeout(value = 10, timeUnit = MINUTES) - -public class MutinyMain extends BaseReactiveTest { - - @Override - protected Collection> annotatedEntities() { - return List.of( Book.class, Author.class ); - } - - @Test - public void testWithInsert(VertxTestContext context) { - out.println( "== Mutiny API Example ==" ); - - // obtain a factory for reactive sessions based on the - // standard JPA configuration properties specified in - // resources/META-INF/persistence.xml - - // define some test data - Author author1 = new Author("Iain M. Banks"); - Author author2 = new Author("Neal Stephenson"); - Book book1 = new Book("1-85723-235-6", "Feersum Endjinn", author1, LocalDate.of(1994, JANUARY, 1)); - Book book2 = new Book("0-380-97346-4", "Cryptonomicon", author2, LocalDate.of(1999, MAY, 1)); - Book book3 = new Book("0-553-08853-X", "Snow Crash", author2, LocalDate.of(1992, JUNE, 1)); - author1.getBooks().add(book1); - author2.getBooks().add(book2); - author2.getBooks().add(book3); - - CriteriaBuilder builder = getSessionFactory().getCriteriaBuilder(); - CriteriaQuery query = builder.createQuery( Book.class ); - Root b = query.from( Book.class ); - b.fetch( "author" ); - ParameterExpression t = builder.parameter( String.class ); - query.where( builder.equal( b.get( "title" ), t ) ); - query.orderBy( builder.asc( b.get( "isbn" ) ) ); - - CriteriaUpdate update = builder.createCriteriaUpdate( Book.class ); - b = update.from( Book.class ); - update.where( builder.equal( b.get( "title" ), t ) ); - update.set( b.get( "title" ), "XXX" ); - - test( - context, - getMutinySessionFactory().withStatelessSession(session -> - session.withTransaction(tx -> session.insertAll(author1, author2, book1, book2, book3) - )) - .chain(() -> - getMutinySessionFactory().withStatelessSession( - session -> session.get(Author.class, author1.getId()) - .invoke(author -> out.println("Author.name: " + author.getName()))) - ) - .chain(() -> - getMutinySessionFactory().withStatelessSession( - session -> session.get(Book.class, book3.getId()) - .invoke(book -> out.println("Book.title: " + book.getTitle()))) - ).chain(() -> - getMutinySessionFactory().withStatelessSession( - session -> session.createNativeQuery( - "select book.title, author.name from books book join authors author on book.author_id = author.id order by book.title desc" -// ,Object.class - ) - .getResultList() - .invoke( rows -> { - List topArray = rows; - - for( Object row : topArray ) { - final Object[] theRowArray = (Object[])row; - out.printf("%s : (%s)\n", theRowArray[0], theRowArray[1]); - } - -// rows.forEach( -// row -> out.printf("%s (%s)\n", row) -// ) - } ) - ) - ) - ); - } - - @Test - public void test(VertxTestContext context) { - out.println( "== Mutiny API Example ==" ); - - // obtain a factory for reactive sessions based on the - // standard JPA configuration properties specified in - // resources/META-INF/persistence.xml - - // define some test data - Author author1 = new Author("Iain M. Banks"); - Author author2 = new Author("Neal Stephenson"); - Book book1 = new Book("1-85723-235-6", "Feersum Endjinn", author1, LocalDate.of(1994, JANUARY, 1)); - Book book2 = new Book("0-380-97346-4", "Cryptonomicon", author2, LocalDate.of(1999, MAY, 1)); - Book book3 = new Book("0-553-08853-X", "Snow Crash", author2, LocalDate.of(1992, JUNE, 1)); - author1.getBooks().add(book1); - author2.getBooks().add(book2); - author2.getBooks().add(book3); - - CriteriaBuilder builder = getSessionFactory().getCriteriaBuilder(); - CriteriaQuery query = builder.createQuery( Book.class ); - Root b = query.from( Book.class ); - b.fetch( "author" ); - ParameterExpression t = builder.parameter( String.class ); - query.where( builder.equal( b.get( "title" ), t ) ); - query.orderBy( builder.asc( b.get( "isbn" ) ) ); - - CriteriaUpdate update = builder.createCriteriaUpdate( Book.class ); - b = update.from( Book.class ); - update.where( builder.equal( b.get( "title" ), t ) ); - update.set( b.get( "title" ), "XXX" ); - - test( - context, - getMutinySessionFactory().withTransaction( (session, tx) -> session - .persistAll( author1, author2 ) - .call( session::flush ) - .chain( () -> session.find( Book.class, book1.getId() ) - .invoke( singleBook -> out.println( book1.getTitle() + " is a great book!" ) ) ) - ).chain( () -> - getMutinySessionFactory().withSession( - session -> session.find( Author.class, author1.getId(), author2.getId() ) - .invoke( authors -> authors.forEach( author -> out.println("Author.name: " + author.getName() ) ) ) - ) - ) - - /* - test( - context, - openSession() - .thenCompose( session -> session.persist( author1, author2 ) - .thenCompose( v -> session.flush() ) - ) - .thenCompose( v -> openSession() ) - .thenCompose( session -> session.createQuery( query ) - .setParameter( t, "Snow Crash" ) - .getResultList() ) - .thenAccept( books -> { - assertEquals( 1, books.size() ); - books.forEach( book -> { - assertNotNull( book.id ); - assertNotNull( book.title ); - assertNotNull( book.isbn ); - assertEquals( "Snow Crash", book.title ); - } ); - } ) - - .thenCompose( v -> openSession() ) - .thenCompose( session -> session.createQuery( update ) - .setParameter( t, "Snow Crash" ) - .executeUpdate() ) - .thenCompose( v -> openSession() ) - .thenCompose( session -> session.createQuery( delete ) - .setParameter( t, "Snow Crash" ) - .executeUpdate() ) - ); - */ - ); - } - - /* - try { - // obtain a reactive session - factory.withTransaction( - // persist the Authors with their Books in a transaction - (session, tx) -> session.persistAll( author1, author2 ) - ) - // wait for it to finish - .await().indefinitely(); - - factory.withSession( - // retrieve a Book - session -> session.find( Book.class, book1.getId() ) - // print its title - .invoke( book -> out.println( book.getTitle() + " is a great book!" ) ) - ) - .await().indefinitely(); - - factory.withSession( - // retrieve both Authors at once - session -> session.find( Author.class, author1.getId(), author2.getId() ) - .invoke( authors -> authors.forEach( author -> out.println( author.getName() ) ) ) - ) - .await().indefinitely(); - - factory.withSession( - // retrieve an Author - session -> session.find( Author.class, author2.getId() ) - // lazily fetch their books - .chain( author -> fetch( author.getBooks() ) - // print some info - .invoke( books -> { - out.println( author.getName() + " wrote " + books.size() + " books" ); - books.forEach( book -> out.println( book.getTitle() ) ); - } ) - ) - ) - .await().indefinitely(); - - factory.withSession( - // retrieve the Author lazily from a Book - session -> session.find( Book.class, book1.getId() ) - // fetch a lazy field of the Book - .chain( book -> fetch( book.getAuthor() ) - // print the lazy field - .invoke( author -> out.printf( "%s wrote '%s'\n", author.getName(), book1.getTitle() ) ) - ) - ) - .await().indefinitely(); - - factory.withSession( - // query the Book titles - session -> session.createQuery( - "select title, author.name from Book order by title desc", - Object[].class - ) - .getResultList() - .invoke( rows -> rows.forEach( - row -> out.printf( "%s (%s)\n", row[0], row[1] ) - ) ) - ) - .await().indefinitely(); - - factory.withSession( - // query the entire Book entities - session -> session.createQuery( - "from Book book join fetch book.author order by book.title desc", - Book.class - ) - .getResultList() - .invoke( books -> books.forEach( - b -> out.printf( - "%s: %s (%s)\n", - b.getIsbn(), - b.getTitle(), - b.getAuthor().getName() - ) - ) ) - ) - .await().indefinitely(); - - factory.withSession( - // use a criteria query - session -> { - CriteriaQuery query = factory.getCriteriaBuilder().createQuery( Book.class ); - Root a = query.from( Author.class ); - Join b = a.join( author1.getBooks() ); - query.where( a.get( author1.getName() ).in( "Neal Stephenson", "William Gibson" ) ); - query.select( b ); - return session.createQuery( query ).getResultList().invoke( - books -> books.forEach( book -> out.println( book.getTitle() ) ) - ); - } - ) - .await().indefinitely(); - - factory.withSession( - // retrieve a Book - session -> session.find( Book.class, book1.getId() ) - // fetch a lazy field of the Book - .call( book -> session.fetch( book, book1.getPublished() ) - // print one lazy field - .invoke( published -> out.printf( - "'%s' was published in %d\n", - book.getTitle(), - published.getYear() - ) ) - ) - .call( book -> session.fetch( book, book1.coverImage ) - // print the other lazy field - .invoke( coverImage -> out.println( new String( coverImage ) ) ) - ) - ) - .await().indefinitely(); - - factory.withTransaction( - // retrieve a Book - (session, tx) -> session.find( Book.class, book2.getId() ) - // delete the Book - .chain( session::remove ) - ) - .await().indefinitely(); - - factory.withTransaction( - // delete all the Books in a transaction - (session, tx) -> session.createQuery( "delete Book" ).executeUpdate() - //delete all the Authors - .call( () -> session.createQuery( "delete Author" ).executeUpdate() ) - ) - .await().indefinitely(); - - } - finally { - // remember to shut down the factory - factory.close(); - } - }} - */ - - @Entity - @Table(name="authors") - public static class Author { - @Id - @GeneratedValue - private Integer id; - - @NotNull - private String name; - - @OneToMany(mappedBy = "author", cascade = CascadeType.PERSIST) - private List books = new ArrayList<>(); - - public Author(String name) { - super(); - this.name = name; - } - - public Author() {} - - Integer getId() { - return id; - } - - String getName() { - return name; - } - - List getBooks() { - return books; - } - } - - - @Entity - @Table(name="books") - public static class Book { - @Id - @GeneratedValue - private Integer id; - - private String isbn; - - @NotNull - private String title; - - @Basic(fetch = LAZY) - @NotNull - private LocalDate published; - - @Basic(fetch = LAZY) - public byte[] coverImage; - - @NotNull - @ManyToOne(fetch = LAZY) - private Author author; - - public Book(String isbn, String title, Author author, LocalDate published) { - super(); - this.title = title; - this.isbn = isbn; - this.author = author; - this.published = published; - this.coverImage = ("Cover image for '" + title + "'").getBytes(); - } - - public Book() {} - - Integer getId() { - return id; - } - - String getIsbn() { - return isbn; - } - - String getTitle() { - return title; - } - - Author getAuthor() { - return author; - } - - LocalDate getPublished() { - return published; - } - - byte[] getCoverImage() { - return coverImage; - } - } -} From 34743891612723b0d556fdcce50c8dcae4dbf58f Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 4 Aug 2023 15:36:12 +0200 Subject: [PATCH 04/14] [#1718] Fix integration with Hibernate ORM 6.3 * Fix compilation errors * Add ReactiveArrayJdbcTypeConstructor * Remove duplicated methods from ORM --- .../ReactiveEntityRegularInsertAction.java | 28 +-- .../impl/ReactiveEntityUpdateAction.java | 82 +-------- .../ReactiveMutationExecutorPostInsert.java | 4 +- ...MutationExecutorPostInsertSingleTable.java | 9 +- .../DefaultReactiveLoadEventListener.java | 2 +- .../ReactiveAbstractMultiIdEntityLoader.java | 11 +- .../ReactiveCollectionLoaderNamedQuery.java | 10 ++ .../ReactiveEntityBatchLoaderArrayParam.java | 64 +++---- .../ReactiveEntityBatchLoaderInPredicate.java | 58 +++---- ...ReactiveMultiIdEntityLoaderArrayParam.java | 37 ++-- .../ReactiveNaturalIdLoaderDelegate.java | 5 +- ...ctiveSingleIdEntityLoaderStandardImpl.java | 163 +++--------------- .../internal/ReactiveSingleIdLoadPlan.java | 3 +- .../ast/spi/ReactiveMultiIdEntityLoader.java | 15 +- .../ReactiveAbstractCollectionPersister.java | 23 +-- .../ReactiveBasicCollectionPersister.java | 20 +-- .../impl/ReactiveOneToManyPersister.java | 45 ++--- ...ReactiveDeleteRowsCoordinatorStandard.java | 8 +- ...ReactiveInsertRowsCoordinatorStandard.java | 14 +- .../ReactiveRemoveCoordinatorStandard.java | 16 +- ...eactiveUpdateRowsCoordinatorOneToMany.java | 36 ++-- .../impl/ReactiveAbstractEntityPersister.java | 8 +- .../ReactiveAbstractPersisterDelegate.java | 85 ++++----- ...ReactiveJoinedSubclassEntityPersister.java | 17 +- .../ReactiveSingleTableEntityPersister.java | 20 ++- .../ReactiveUnionSubclassEntityPersister.java | 18 +- .../provider/ReactivePersistenceProvider.java | 46 +++-- .../impl/ReactiveTypeContributor.java | 7 +- .../spi/ReactiveAbstractSelectionQuery.java | 12 +- .../sqm/internal/ReactiveQuerySqmImpl.java | 2 +- .../ReactiveSqmSelectionQueryImpl.java | 2 +- .../ReactiveAbstractCteMutationHandler.java | 2 +- .../impl/ReactiveSessionFactoryImpl.java | 4 - .../session/impl/ReactiveSessionImpl.java | 113 +----------- .../impl/ReactiveStatelessSessionImpl.java | 119 +------------ ...activeStandardMutationExecutorService.java | 16 +- .../ReactiveDeferredResultSetAccess.java | 10 +- .../internal/ReactiveResultsHelper.java | 5 + .../ReactiveArrayJdbcTypeConstructor.java | 42 +++++ .../reactive/types/JoinColumnsTest.java | 37 ++-- 40 files changed, 403 insertions(+), 815 deletions(-) create mode 100644 hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveArrayJdbcTypeConstructor.java diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityRegularInsertAction.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityRegularInsertAction.java index 0e2045521..b6339a6b8 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityRegularInsertAction.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityRegularInsertAction.java @@ -11,17 +11,13 @@ import org.hibernate.HibernateException; import org.hibernate.action.internal.AbstractEntityInsertAction; import org.hibernate.action.internal.EntityInsertAction; -import org.hibernate.cache.spi.access.EntityDataAccess; -import org.hibernate.cache.spi.entry.CacheEntry; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.event.spi.EventSource; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; -import org.hibernate.stat.internal.StatsHelper; import org.hibernate.stat.spi.StatisticsImplementor; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; @@ -88,7 +84,7 @@ public CompletionStage reactiveExecute() throws HibernateException { postInsert(); final StatisticsImplementor statistics = session.getFactory().getStatistics(); - if ( statistics.isStatisticsEnabled() && !veto ) { + if ( statistics.isStatisticsEnabled() ) { statistics.insertEntity( getPersister().getEntityName() ); } @@ -104,28 +100,6 @@ public CompletionStage reactiveExecute() throws HibernateException { } } - //TODO: copy/paste from superclass (make it protected) - private void putCacheIfNecessary() { - final EntityPersister persister = getPersister(); - final SharedSessionContractImplementor session = getSession(); - if ( isCachePutEnabled( persister, session ) ) { - final SessionFactoryImplementor factory = session.getFactory(); - final CacheEntry ce = persister.buildCacheEntry( getInstance(), getState(), getVersion(), session ); - setCacheEntry( persister.getCacheEntryStructure().structure( ce ) ); - final EntityDataAccess cache = persister.getCacheAccessStrategy(); - final Object ck = cache.generateCacheKey( getId(), persister, factory, session.getTenantIdentifier() ); - final boolean put = cacheInsert( persister, ck ); - - final StatisticsImplementor statistics = factory.getStatistics(); - if ( put && statistics.isStatisticsEnabled() ) { - statistics.entityCachePut( - StatsHelper.INSTANCE.getRootEntityRole( persister ), - cache.getRegion().getName() - ); - } - } - } - private CompletionStage processInsertGeneratedProperties( ReactiveEntityPersister persister, SharedSessionContractImplementor session, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityUpdateAction.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityUpdateAction.java index 9ef65faee..3c893f676 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityUpdateAction.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityUpdateAction.java @@ -8,21 +8,15 @@ import java.util.concurrent.CompletionStage; import org.hibernate.AssertionFailure; -import org.hibernate.CacheMode; import org.hibernate.HibernateException; import org.hibernate.action.internal.EntityUpdateAction; -import org.hibernate.cache.spi.access.EntityDataAccess; -import org.hibernate.cache.spi.entry.CacheEntry; -import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.event.spi.EventSource; -import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.reactive.engine.ReactiveExecutable; import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister; -import org.hibernate.stat.internal.StatsHelper; import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.type.TypeHelper; @@ -101,7 +95,7 @@ public CompletionStage reactiveExecute() throws HibernateException { } ) .thenCompose( this::handleGeneratedProperties ) .thenAccept( entry -> { - handleDeleted( entry, persister, instance ); + handleDeleted( entry ); updateCacheItem( persister, ck, entry ); handleNaturalIdResolutions( persister, session, id ); postUpdate(); @@ -142,88 +136,20 @@ private CompletionStage handleGeneratedProperties(EntityEntry entry } // TODO: copy/paste from superclass (make it protected) - private void handleDeleted(EntityEntry entry, EntityPersister persister, Object instance) { + private void handleDeleted(EntityEntry entry) { if ( entry.getStatus() == Status.DELETED ) { - final EntityMetamodel entityMetamodel = persister.getEntityMetamodel(); + final EntityMetamodel entityMetamodel = getPersister().getEntityMetamodel(); final boolean isImpliedOptimisticLocking = !entityMetamodel.isVersioned() && entityMetamodel.getOptimisticLockStyle().isAllOrDirty(); if ( isImpliedOptimisticLocking && entry.getLoadedState() != null ) { // The entity will be deleted and because we are going to create a delete statement // that uses all the state values in the where clause, the entry state needs to be // updated otherwise the statement execution will not delete any row (see HHH-15218). - entry.postUpdate(instance, getState(), getNextVersion() ); + entry.postUpdate( getInstance(), getState(), getNextVersion() ); } } } - // TODO: copy/paste from superclass (make it protected) - private void handleNaturalIdResolutions(EntityPersister persister, SharedSessionContractImplementor session, Object id) { - NaturalIdMapping naturalIdMapping = getNaturalIdMapping(); - if ( naturalIdMapping != null ) { - session.getPersistenceContextInternal().getNaturalIdResolutions().manageSharedResolution( - id, - naturalIdMapping.extractNaturalIdFromEntityState( getState() ), - getPreviousNaturalIdValues(), - persister, - CachedNaturalIdValueSource.UPDATE - ); - } - } - - // TODO: copy/paste from superclass (make it protected) - private void updateCacheItem(Object previousVersion, Object ck, EntityEntry entry) { - final EntityPersister persister = getPersister(); - if ( persister.canWriteToCache() ) { - final SharedSessionContractImplementor session = getSession(); - if ( isCacheInvalidationRequired( persister, session ) || entry.getStatus() != Status.MANAGED ) { - persister.getCacheAccessStrategy().remove( session, ck ); - } - else if ( session.getCacheMode().isPutEnabled() ) { - //TODO: inefficient if that cache is just going to ignore the updated state! - final CacheEntry ce = persister.buildCacheEntry( getInstance(), getState(), getNextVersion(), getSession() ); - setCacheEntry( persister.getCacheEntryStructure().structure( ce ) ); - final boolean put = updateCache( persister, previousVersion, ck ); - - final StatisticsImplementor statistics = session.getFactory().getStatistics(); - if ( put && statistics.isStatisticsEnabled() ) { - statistics.entityCachePut( - StatsHelper.INSTANCE.getRootEntityRole(persister), - getPersister().getCacheAccessStrategy().getRegion().getName() - ); - } - } - } - } - - private static boolean isCacheInvalidationRequired( - EntityPersister persister, - SharedSessionContractImplementor session) { - // the cache has to be invalidated when CacheMode is equal to GET or IGNORE - return persister.isCacheInvalidationRequired() - || session.getCacheMode() == CacheMode.GET - || session.getCacheMode() == CacheMode.IGNORE; - } - - // TODO: copy/paste from superclass (make it protected) - private Object lockCacheItem(Object previousVersion) { - final EntityPersister persister = getPersister(); - if ( persister.canWriteToCache() ) { - final SharedSessionContractImplementor session = getSession(); - final EntityDataAccess cache = persister.getCacheAccessStrategy(); - final Object ck = cache.generateCacheKey( - getId(), - persister, - session.getFactory(), - session.getTenantIdentifier() - ); - setLock( cache.lockItem( session, ck, previousVersion ) ); - return ck; - } - else { - return null; - } - } - private CompletionStage processGeneratedProperties( Object id, ReactiveEntityPersister persister, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java index 5b5f43bd7..9a382c6cd 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java @@ -24,13 +24,13 @@ import org.hibernate.reactive.id.insert.ReactiveInsertGeneratedIdentifierDelegate; import org.hibernate.reactive.pool.ReactiveConnection; import org.hibernate.reactive.session.ReactiveConnectionSupplier; -import org.hibernate.sql.model.MutationOperationGroup; +import org.hibernate.sql.model.EntityMutationOperationGroup; import org.hibernate.sql.model.ValuesAnalysis; public class ReactiveMutationExecutorPostInsert extends MutationExecutorPostInsert implements ReactiveMutationExecutor { public ReactiveMutationExecutorPostInsert( - MutationOperationGroup mutationOperationGroup, + EntityMutationOperationGroup mutationOperationGroup, SharedSessionContractImplementor session) { super( mutationOperationGroup, session ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java index d18435a1c..c469ac6d5 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java @@ -18,7 +18,7 @@ import org.hibernate.reactive.engine.jdbc.env.internal.ReactiveMutationExecutor; import org.hibernate.reactive.id.insert.ReactiveInsertGeneratedIdentifierDelegate; import org.hibernate.sql.exec.spi.JdbcParameterBinder; -import org.hibernate.sql.model.MutationOperationGroup; +import org.hibernate.sql.model.EntityMutationOperationGroup; import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.PreparableMutationOperation; import org.hibernate.sql.model.TableMapping; @@ -36,10 +36,11 @@ public class ReactiveMutationExecutorPostInsertSingleTable extends MutationExecu private final EntityMutationTarget mutationTarget; private final PreparedStatementDetails identityInsertStatementDetails; - public ReactiveMutationExecutorPostInsertSingleTable(MutationOperationGroup mutationOperationGroup, SharedSessionContractImplementor session) { + public ReactiveMutationExecutorPostInsertSingleTable(EntityMutationOperationGroup mutationOperationGroup, SharedSessionContractImplementor session) { super( mutationOperationGroup, session ); - this.mutationTarget = (EntityMutationTarget) mutationOperationGroup.getMutationTarget(); - final PreparableMutationOperation operation = mutationOperationGroup.getOperation( mutationTarget.getIdentifierTableName() ); + this.mutationTarget = mutationOperationGroup.getMutationTarget(); + final PreparableMutationOperation operation = (PreparableMutationOperation) mutationOperationGroup + .getOperation( mutationTarget.getIdentifierTableName() ); this.identityInsertStatementDetails = identityPreparation( operation, session ); } 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 224b4552a..ae79148d1 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 @@ -421,7 +421,7 @@ private static PersistentAttributeInterceptable createBatchLoadableEnhancedProxy EntityPersister persister, EntityKey keyToLoad, EventSource session) { - if ( keyToLoad.isBatchLoadable() ) { + if ( keyToLoad.isBatchLoadable( session.getLoadQueryInfluencers() ) ) { // Add a batch-fetch entry into the queue for this entity session.getPersistenceContextInternal().getBatchFetchQueue().addBatchLoadableEntityKey( keyToLoad ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractMultiIdEntityLoader.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractMultiIdEntityLoader.java index eb234ea58..527d59326 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractMultiIdEntityLoader.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractMultiIdEntityLoader.java @@ -11,7 +11,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.spi.EventSource; -import org.hibernate.loader.ast.internal.Preparable; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -20,7 +19,7 @@ /** * @see org.hibernate.loader.ast.internal.AbstractMultiIdEntityLoader */ -public abstract class ReactiveAbstractMultiIdEntityLoader implements ReactiveMultiIdEntityLoader, Preparable { +public abstract class ReactiveAbstractMultiIdEntityLoader implements ReactiveMultiIdEntityLoader { private final EntityMappingType entityDescriptor; private final SessionFactoryImplementor sessionFactory; @@ -30,11 +29,7 @@ public abstract class ReactiveAbstractMultiIdEntityLoader implements Reactive public ReactiveAbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { this.entityDescriptor = entityDescriptor; this.sessionFactory = sessionFactory; - } - - @Override - public void prepare() { - identifierMapping = getLoadable().getIdentifierMapping(); + this.identifierMapping = getLoadable().getIdentifierMapping(); } protected EntityMappingType getEntityDescriptor() { @@ -55,7 +50,7 @@ public EntityMappingType getLoadable() { } @Override - public final CompletionStage> load(K[] ids, MultiIdLoadOptions loadOptions, EventSource session) { + public final CompletionStage> reactiveLoad(K[] ids, MultiIdLoadOptions loadOptions, EventSource session) { Objects.requireNonNull( ids ); return loadOptions.isOrderReturnEnabled() diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionLoaderNamedQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionLoaderNamedQuery.java index b89b42260..c7d43330a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionLoaderNamedQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionLoaderNamedQuery.java @@ -10,12 +10,22 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.PluralAttributeMapping; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.query.named.NamedQueryMemento; /** * @see org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery */ public class ReactiveCollectionLoaderNamedQuery implements ReactiveCollectionLoader { + private final CollectionPersister persister; + private final NamedQueryMemento namedQueryMemento; + + public ReactiveCollectionLoaderNamedQuery(CollectionPersister persister, NamedQueryMemento namedQueryMemento) { + this.persister = persister; + this.namedQueryMemento = namedQueryMemento; + } + @Override public PluralAttributeMapping getLoadable() { throw new UnsupportedOperationException(); 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 fab9a6eaa..b0b60b6eb 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 @@ -18,7 +18,6 @@ import org.hibernate.loader.ast.internal.EntityBatchLoaderArrayParam; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.MultiKeyLoadHelper; -import org.hibernate.loader.ast.internal.Preparable; import org.hibernate.loader.ast.spi.EntityBatchLoader; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; @@ -31,8 +30,6 @@ import org.hibernate.sql.exec.internal.JdbcParameterImpl; import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect; import org.hibernate.sql.exec.spi.JdbcParameterBindings; -import org.hibernate.type.BasicType; -import org.hibernate.type.BasicTypeRegistry; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; @@ -41,7 +38,7 @@ * @see EntityBatchLoaderArrayParam */ public class ReactiveEntityBatchLoaderArrayParam extends ReactiveSingleIdEntityLoaderSupport - implements EntityBatchLoader>, ReactiveSingleIdEntityLoader, SqlArrayMultiKeyLoader, Preparable { + implements EntityBatchLoader>, ReactiveSingleIdEntityLoader, SqlArrayMultiKeyLoader { private final int domainBatchSize; @@ -65,6 +62,32 @@ public ReactiveEntityBatchLoaderArrayParam( domainBatchSize ); } + + identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping(); + final Class arrayClass = + Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass(); + arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( + sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ), + identifierMapping.getJdbcMapping(), + arrayClass, + sessionFactory + ); + + jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); + sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter( + getLoadable(), + identifierMapping, + new LoadQueryInfluencers( sessionFactory ), + LockOptions.NONE, + jdbcParameter, + sessionFactory + ); + + jdbcSelectOperation = sessionFactory.getJdbcServices() + .getJdbcEnvironment() + .getSqlAstTranslatorFactory() + .buildSelectTranslator( sessionFactory, sqlAst ) + .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); } @Override @@ -145,39 +168,6 @@ private CompletionStage initializeEntities( } ); } - @Override - public void prepare() { - identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping(); - final Class arrayClass = Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ) - .getClass(); - - final BasicTypeRegistry basicTypeRegistry = sessionFactory.getTypeConfiguration().getBasicTypeRegistry(); - final BasicType arrayBasicType = basicTypeRegistry.getRegisteredType( arrayClass ); - - arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - arrayBasicType, - identifierMapping.getJdbcMapping(), - arrayClass, - sessionFactory - ); - - jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); - sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter( - getLoadable(), - identifierMapping, - LoadQueryInfluencers.NONE, - LockOptions.NONE, - jdbcParameter, - sessionFactory - ); - - jdbcSelectOperation = sessionFactory.getJdbcServices() - .getJdbcEnvironment() - .getSqlAstTranslatorFactory() - .buildSelectTranslator( sessionFactory, sqlAst ) - .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); - } - @Override public String toString() { return String.format( diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java index 0a403a174..78403e41f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java @@ -18,7 +18,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; -import org.hibernate.loader.ast.internal.Preparable; import org.hibernate.loader.ast.spi.EntityBatchLoader; import org.hibernate.loader.ast.spi.SqlInPredicateMultiKeyLoader; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; @@ -37,7 +36,7 @@ * @see org.hibernate.loader.ast.internal.EntityBatchLoaderInPredicate */ public class ReactiveEntityBatchLoaderInPredicate extends ReactiveSingleIdEntityLoaderSupport - implements EntityBatchLoader>, SqlInPredicateMultiKeyLoader, Preparable { + implements EntityBatchLoader>, SqlInPredicateMultiKeyLoader { private final int domainBatchSize; private final int sqlBatchSize; @@ -67,6 +66,32 @@ public ReactiveEntityBatchLoaderInPredicate( sqlBatchSize ); } + + final EntityIdentifierMapping identifierMapping = getLoadable().getIdentifierMapping(); + + final int expectedNumberOfParameters = identifierMapping.getJdbcTypeCount() * sqlBatchSize; + + final JdbcParametersList.Builder jdbcParametersBuilder = JdbcParametersList.newBuilder( expectedNumberOfParameters ); + sqlAst = LoaderSelectBuilder.createSelect( + getLoadable(), + // null here means to select everything + null, + identifierMapping, + null, + sqlBatchSize, + new LoadQueryInfluencers( sessionFactory ), + LockOptions.NONE, + jdbcParametersBuilder::add, + sessionFactory + ); + this.jdbcParameters = jdbcParametersBuilder.build(); + assert jdbcParameters.size() == expectedNumberOfParameters; + + jdbcSelectOperation = sessionFactory.getJdbcServices() + .getJdbcEnvironment() + .getSqlAstTranslatorFactory() + .buildSelectTranslator( sessionFactory, sqlAst ) + .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); } @Override @@ -179,35 +204,6 @@ protected CompletionStage initializeEntities( ); } - @Override - public void prepare() { - EntityIdentifierMapping identifierMapping = getLoadable().getIdentifierMapping(); - - final int expectedNumberOfParameters = identifierMapping.getJdbcTypeCount() * sqlBatchSize; - - final JdbcParametersList.Builder parametersListBuilder = JdbcParametersList.newBuilder( expectedNumberOfParameters ); - sqlAst = LoaderSelectBuilder.createSelect( - getLoadable(), - // null here means to select everything - null, - identifierMapping, - null, - sqlBatchSize, - LoadQueryInfluencers.NONE, - LockOptions.NONE, - parametersListBuilder::add, - sessionFactory - ); - final JdbcParametersList jdbcParameters = parametersListBuilder.build(); - assert jdbcParameters.size() == expectedNumberOfParameters; - - jdbcSelectOperation = sessionFactory.getJdbcServices() - .getJdbcEnvironment() - .getSqlAstTranslatorFactory() - .buildSelectTranslator( sessionFactory, sqlAst ) - .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); - } - @Override public String toString() { return String.format( 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 b37a780fd..967581dbb 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 @@ -27,7 +27,6 @@ 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.MultiKeyLoadHelper; import org.hibernate.loader.ast.internal.MultiKeyLoadLogging; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; @@ -46,10 +45,10 @@ import org.hibernate.sql.exec.spi.JdbcParametersList; import org.hibernate.sql.results.internal.RowTransformerStandardImpl; import org.hibernate.type.BasicType; -import org.hibernate.type.BasicTypeRegistry; 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.reactive.loader.ast.internal.ReactiveLoaderHelper.loadByArrayParameter; import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; import static org.hibernate.reactive.util.impl.CompletionStages.loop; @@ -60,13 +59,24 @@ */ public class ReactiveMultiIdEntityLoaderArrayParam extends ReactiveAbstractMultiIdEntityLoader { - private JdbcMapping arrayJdbcMapping; - private JdbcParameter jdbcParameter; + private final JdbcMapping arrayJdbcMapping; + private final JdbcParameter jdbcParameter; public ReactiveMultiIdEntityLoaderArrayParam( EntityMappingType entityDescriptor, 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; + jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); } @Override @@ -402,23 +412,4 @@ private X[] createTypedArray(@SuppressWarnings("SameParameterValue") int len //noinspection unchecked return (X[]) Array.newInstance( getIdentifierMapping().getJavaType().getJavaTypeClass(), length ); } - - @Override - public void prepare() { - super.prepare(); - - final Class arrayClass = createTypedArray( 0 ).getClass(); - - final BasicTypeRegistry basicTypeRegistry = getSessionFactory().getTypeConfiguration().getBasicTypeRegistry(); - final BasicType arrayBasicType = basicTypeRegistry.getRegisteredType( arrayClass ); - - arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - arrayBasicType, - getIdentifierMapping().getJdbcMapping(), - arrayClass, - getSessionFactory() - ); - jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); - } - } 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 8c11c087c..4d9c8dc70 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 @@ -118,11 +118,10 @@ public CompletionStage resolveNaturalIdToId( naturalIdMapping().normalizeInput( naturalIdValue ), NaturalIdLoadOptions.NONE, (tableGroup, creationState) -> entityDescriptor().getIdentifierMapping().createDomainResult( - tableGroup.getNavigablePath().append( EntityIdentifierMapping.ROLE_LOCAL_NAME ), + tableGroup.getNavigablePath().append( EntityIdentifierMapping.ID_ROLE_NAME ), tableGroup, null, - creationState - ), + creationState ), ReactiveNaturalIdLoaderDelegate::visitFetches, ReactiveNaturalIdLoaderDelegate::statsEnabled, (result, startToken) -> { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdEntityLoaderStandardImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdEntityLoaderStandardImpl.java index 9f2f1d3b2..bdb9d692a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdEntityLoaderStandardImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdEntityLoaderStandardImpl.java @@ -5,21 +5,15 @@ */ package org.hibernate.reactive.loader.ast.internal; -import java.util.EnumMap; import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicInteger; -import org.hibernate.Internal; -import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl; -import org.hibernate.loader.ast.spi.CascadingFetchProfile; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.persister.entity.Loadable; import org.hibernate.reactive.loader.ast.spi.ReactiveSingleIdEntityLoader; import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.exec.spi.JdbcParametersList; @@ -29,177 +23,66 @@ * * @see SingleIdEntityLoaderStandardImpl */ -public class ReactiveSingleIdEntityLoaderStandardImpl extends SingleIdEntityLoaderStandardImpl> implements ReactiveSingleIdEntityLoader { - - private EnumMap selectByLockMode = new EnumMap<>( LockMode.class ); - private EnumMap selectByInternalCascadeProfile; - - private AtomicInteger nonReusablePlansGenerated = new AtomicInteger(); - - @Override - public AtomicInteger getNonReusablePlansGenerated() { - return nonReusablePlansGenerated; - } +public class ReactiveSingleIdEntityLoaderStandardImpl extends SingleIdEntityLoaderStandardImpl> + implements ReactiveSingleIdEntityLoader { private DatabaseSnapshotExecutor databaseSnapshotExecutor; - private final EntityMappingType entityDescriptor; - public ReactiveSingleIdEntityLoaderStandardImpl( EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { - super( entityDescriptor, sessionFactory ); - // todo (6.0) : consider creating a base AST and "cloning" it - this.entityDescriptor = entityDescriptor; - } - - @Override - public EntityMappingType getLoadable() { - return entityDescriptor; + super( + entityDescriptor, + sessionFactory, + (lockOptions, influencers) -> createLoadPlan( entityDescriptor, lockOptions, influencers, sessionFactory ) + ); } @Override public CompletionStage reactiveLoadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) { if ( databaseSnapshotExecutor == null ) { - databaseSnapshotExecutor = new DatabaseSnapshotExecutor( entityDescriptor, sessionFactory ); + databaseSnapshotExecutor = new DatabaseSnapshotExecutor( getLoadable(), sessionFactory ); } return databaseSnapshotExecutor.loadDatabaseSnapshot( id, session ); } - @Override - public void prepare() { - // see `org.hibernate.persister.entity.AbstractEntityPersister#createLoaders` - // we should pre-load a few - maybe LockMode.NONE and LockMode.READ - final LockOptions lockOptions = LockOptions.NONE; - final LoadQueryInfluencers queryInfluencers = new LoadQueryInfluencers( sessionFactory ); - final ReactiveSingleIdLoadPlan plan = createLoadPlan( - lockOptions, - queryInfluencers, - sessionFactory - ); - if ( determineIfReusable( lockOptions, queryInfluencers ) ) { - selectByLockMode.put( lockOptions.getLockMode(), plan ); - } - } - - private boolean determineIfReusable(LockOptions lockOptions, LoadQueryInfluencers loadQueryInfluencers) { - if ( getLoadable().isAffectedByEntityGraph( loadQueryInfluencers ) ) { - return false; - } - - if ( getLoadable().isAffectedByEnabledFetchProfiles( loadQueryInfluencers ) ) { - return false; - } - - //noinspection RedundantIfStatement - if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) { - return false; - } - - return true; - } - - @Override - public CompletionStage load(Object key, LockOptions lockOptions, Boolean readOnly, SharedSessionContractImplementor session) { - final ReactiveSingleIdLoadPlan loadPlan = resolveLoadPlan( lockOptions, session.getLoadQueryInfluencers(), session.getFactory() ); - return loadPlan.load( key, readOnly, true, session ); - } - @Override public CompletionStage load( Object key, - Object entityInstance, LockOptions lockOptions, Boolean readOnly, SharedSessionContractImplementor session) { - final ReactiveSingleIdLoadPlan loadPlan = resolveLoadPlan( + final ReactiveSingleIdLoadPlan loadPlan = (ReactiveSingleIdLoadPlan) resolveLoadPlan( lockOptions, session.getLoadQueryInfluencers(), session.getFactory() ); - - return loadPlan.load( key, entityInstance, readOnly, false, session ); + return loadPlan.load( key, readOnly, true, session ); } - @Internal @Override - public ReactiveSingleIdLoadPlan resolveLoadPlan( + public CompletionStage load( + Object key, + Object entityInstance, LockOptions lockOptions, - LoadQueryInfluencers loadQueryInfluencers, - SessionFactoryImplementor sessionFactory) { - if ( getLoadable().isAffectedByEnabledFilters( loadQueryInfluencers ) ) { - // special case of not-cacheable based on enabled filters effecting this load. - // - // This case is special because the filters need to be applied in order to - // properly restrict the SQL/JDBC results. For this reason it has higher - // precedence than even "internal" fetch profiles. - nonReusablePlansGenerated.incrementAndGet(); - return createLoadPlan( lockOptions, loadQueryInfluencers, sessionFactory ); - } - - final CascadingFetchProfile enabledCascadingFetchProfile = loadQueryInfluencers.getEnabledCascadingFetchProfile(); - if ( enabledCascadingFetchProfile != null ) { - if ( LockMode.WRITE.greaterThan( lockOptions.getLockMode() ) ) { - if ( selectByInternalCascadeProfile == null ) { - selectByInternalCascadeProfile = new EnumMap<>( CascadingFetchProfile.class ); - } - else { - final ReactiveSingleIdLoadPlan existing = selectByInternalCascadeProfile.get( enabledCascadingFetchProfile ); - if ( existing != null ) { - //noinspection unchecked - return existing; - } - } - - final ReactiveSingleIdLoadPlan plan = createLoadPlan( - lockOptions, - loadQueryInfluencers, - sessionFactory - ); - selectByInternalCascadeProfile.put( enabledCascadingFetchProfile, plan ); - return plan; - } - } - - // otherwise see if the loader for the requested load can be cached - which - // also means we should look in the cache for an existing one - - final boolean reusable = determineIfReusable( lockOptions, loadQueryInfluencers ); - - if ( reusable ) { - final ReactiveSingleIdLoadPlan existing = selectByLockMode.get( lockOptions.getLockMode() ); - if ( existing != null ) { - //noinspection unchecked - return existing; - } - - final ReactiveSingleIdLoadPlan plan = createLoadPlan( - lockOptions, - loadQueryInfluencers, - sessionFactory - ); - selectByLockMode.put( lockOptions.getLockMode(), plan ); - - return plan; - } - - nonReusablePlansGenerated.incrementAndGet(); - return createLoadPlan( lockOptions, loadQueryInfluencers, sessionFactory ); + Boolean readOnly, + SharedSessionContractImplementor session) { + final ReactiveSingleIdLoadPlan loadPlan = (ReactiveSingleIdLoadPlan) resolveLoadPlan( lockOptions, session.getLoadQueryInfluencers(), session.getFactory() ); + return loadPlan.load( key, entityInstance, readOnly, false, session ); } - private ReactiveSingleIdLoadPlan createLoadPlan( + private static ReactiveSingleIdLoadPlan createLoadPlan( + EntityMappingType loadable, LockOptions lockOptions, LoadQueryInfluencers queryInfluencers, SessionFactoryImplementor sessionFactory) { - - final JdbcParametersList.Builder jdbcParametersListBuilder = JdbcParametersList.newBuilder(); final SelectStatement sqlAst = LoaderSelectBuilder.createSelect( - getLoadable(), + loadable, // null here means to select everything null, - getLoadable().getIdentifierMapping(), + loadable.getIdentifierMapping(), null, 1, queryInfluencers, @@ -210,8 +93,8 @@ private ReactiveSingleIdLoadPlan createLoadPlan( final JdbcParametersList jdbcParameters = jdbcParametersListBuilder.build(); return new ReactiveSingleIdLoadPlan<>( - (Loadable) getLoadable(), - getLoadable().getIdentifierMapping(), + loadable, + loadable.getIdentifierMapping(), sqlAst, jdbcParameters, lockOptions, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdLoadPlan.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdLoadPlan.java index bfe274e13..efec8f373 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdLoadPlan.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveSingleIdLoadPlan.java @@ -15,6 +15,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.loader.ast.internal.SingleIdLoadPlan; +import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.persister.entity.Loadable; import org.hibernate.query.internal.SimpleQueryOptions; @@ -35,7 +36,7 @@ public class ReactiveSingleIdLoadPlan extends SingleIdLoadPlan> { public ReactiveSingleIdLoadPlan( - Loadable persister, + EntityMappingType persister, ModelPart restrictivePart, SelectStatement sqlAst, JdbcParametersList jdbcParameters, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/spi/ReactiveMultiIdEntityLoader.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/spi/ReactiveMultiIdEntityLoader.java index c0a8cdb2a..47050b139 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/spi/ReactiveMultiIdEntityLoader.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/spi/ReactiveMultiIdEntityLoader.java @@ -9,13 +9,22 @@ import java.util.concurrent.CompletionStage; import org.hibernate.event.spi.EventSource; -import org.hibernate.loader.ast.spi.EntityMultiLoader; +import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.reactive.logging.impl.Log; + +import static java.lang.invoke.MethodHandles.lookup; +import static org.hibernate.reactive.logging.impl.LoggerFactory.make; /** * @see org.hibernate.loader.ast.spi.MultiIdEntityLoader */ -public interface ReactiveMultiIdEntityLoader extends EntityMultiLoader> { +public interface ReactiveMultiIdEntityLoader extends MultiIdEntityLoader { + + @Override + default List load(K[] ids, MultiIdLoadOptions options, EventSource session) { + throw make( Log.class, lookup() ).nonReactiveMethodCall( "reactiveLoad" ); + } - CompletionStage> load(K[] ids, MultiIdLoadOptions options, EventSource session); + CompletionStage> reactiveLoad(K[] ids, MultiIdLoadOptions options, EventSource session); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveAbstractCollectionPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveAbstractCollectionPersister.java index d3382c556..09850965c 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveAbstractCollectionPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveAbstractCollectionPersister.java @@ -10,8 +10,10 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.loader.ast.spi.BatchLoaderFactory; import org.hibernate.loader.ast.spi.CollectionLoader; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.query.named.NamedQueryMemento; +import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoaderNamedQuery; import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoaderSingleKey; import org.hibernate.reactive.pool.ReactiveConnection; import org.hibernate.reactive.session.ReactiveConnectionSupplier; @@ -26,18 +28,17 @@ default ReactiveConnection getReactiveConnection(SharedSessionContractImplemento return ( (ReactiveConnectionSupplier) session ).getReactiveConnection(); } - default boolean isCollectionLoaderReusable(LoadQueryInfluencers loadQueryInfluencers) { - // we can reuse it so long as none of the enabled influencers affect it - return loadQueryInfluencers == LoadQueryInfluencers.NONE || getAttributeMapping().isNotAffectedByInfluencers( loadQueryInfluencers ); + /** + * See org.hibernate.persister.collection.AbstractCollectionPersister#createNamedQueryCollectionLoader + */ + default CollectionLoader createNamedQueryCollectionLoader(CollectionPersister persister, NamedQueryMemento namedQueryMemento) { + return new ReactiveCollectionLoaderNamedQuery(persister, namedQueryMemento); } - default CollectionLoader generateCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { - final int batchSize = getBatchSize(); - if ( batchSize > 1 ) { - return getFactory().getServiceRegistry() - .getService( BatchLoaderFactory.class ) - .createCollectionBatchLoader( batchSize, loadQueryInfluencers, getAttributeMapping(), getFactory() ); - } + /** + * See org.hibernate.persister.collection.AbstractCollectionPersister#createSingleKeyCollectionLoader + */ + default CollectionLoader createSingleKeyCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { return new ReactiveCollectionLoaderSingleKey( getAttributeMapping(), loadQueryInfluencers, getFactory() ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java index 6dc170439..80e312327 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java @@ -19,6 +19,8 @@ import org.hibernate.mapping.Collection; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.collection.BasicCollectionPersister; +import org.hibernate.persister.collection.CollectionPersister; +import org.hibernate.query.named.NamedQueryMemento; import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoader; import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoaderSubSelectFetch; import org.hibernate.reactive.persister.collection.mutation.ReactiveDeleteRowsCoordinator; @@ -48,8 +50,6 @@ public class ReactiveBasicCollectionPersister extends BasicCollectionPersister i private final ReactiveDeleteRowsCoordinator deleteRowsCoordinator; private final ReactiveRemoveCoordinator removeCoordinator; - private CollectionLoader reusableCollectionLoader; - public ReactiveBasicCollectionPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, @@ -63,17 +63,13 @@ public ReactiveBasicCollectionPersister( } @Override - protected CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { - if ( isCollectionLoaderReusable( loadQueryInfluencers ) ) { - if ( reusableCollectionLoader == null ) { - reusableCollectionLoader = ReactiveAbstractCollectionPersister.super - .generateCollectionLoader( LoadQueryInfluencers.NONE ); - } - return reusableCollectionLoader; - } + public CollectionLoader createNamedQueryCollectionLoader(CollectionPersister persister, NamedQueryMemento namedQueryMemento) { + return ReactiveAbstractCollectionPersister.super.createNamedQueryCollectionLoader( persister, namedQueryMemento ); + } - // create a one-off - return ReactiveAbstractCollectionPersister.super.generateCollectionLoader( loadQueryInfluencers ); + @Override + public CollectionLoader createSingleKeyCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { + return ReactiveAbstractCollectionPersister.super.createSingleKeyCollectionLoader( loadQueryInfluencers ); } private ReactiveUpdateRowsCoordinator buildUpdateRowCoordinator() { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java index c713fd9d3..526acea85 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java @@ -24,8 +24,10 @@ import org.hibernate.loader.ast.spi.CollectionLoader; import org.hibernate.mapping.Collection; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; +import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.OneToManyPersister; import org.hibernate.persister.collection.mutation.RowMutationOperations; +import org.hibernate.query.named.NamedQueryMemento; import org.hibernate.reactive.engine.jdbc.env.internal.ReactiveMutationExecutor; import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoader; import org.hibernate.reactive.loader.ast.internal.ReactiveCollectionLoaderSubSelectFetch; @@ -42,14 +44,14 @@ import org.hibernate.reactive.persister.collection.mutation.ReactiveUpdateRowsCoordinatorNoOp; import org.hibernate.reactive.persister.collection.mutation.ReactiveUpdateRowsCoordinatorOneToMany; import org.hibernate.reactive.util.impl.CompletionStages; -import org.hibernate.sql.model.MutationType; -import org.hibernate.sql.model.internal.MutationOperationGroupSingle; import org.hibernate.sql.model.jdbc.JdbcMutationOperation; import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; +import static org.hibernate.sql.model.MutationType.UPDATE; +import static org.hibernate.sql.model.internal.MutationOperationGroupFactory.singleOperation; /** * A reactive {@link OneToManyPersister} @@ -62,20 +64,29 @@ public class ReactiveOneToManyPersister extends OneToManyPersister private final ReactiveDeleteRowsCoordinator deleteRowsCoordinator; private final ReactiveRemoveCoordinator removeCoordinator; - private CollectionLoader reusableCollectionLoader; - public ReactiveOneToManyPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, RuntimeModelCreationContext creationContext) throws MappingException, CacheException { super( collectionBinding, cacheAccessStrategy, creationContext ); - this.insertRowsCoordinator = buildInsertCoordinator(); this.updateRowsCoordinator = buildUpdateCoordinator(); this.deleteRowsCoordinator = buildDeleteCoordinator(); this.removeCoordinator = buildDeleteAllCoordinator(); } + @Override + public CollectionLoader createNamedQueryCollectionLoader( + CollectionPersister persister, + NamedQueryMemento namedQueryMemento) { + return ReactiveAbstractCollectionPersister.super.createNamedQueryCollectionLoader( persister, namedQueryMemento ); + } + + @Override + public CollectionLoader createSingleKeyCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { + return ReactiveAbstractCollectionPersister.super.createSingleKeyCollectionLoader( loadQueryInfluencers ); + } + @Override public ReactiveInsertRowsCoordinator getInsertRowsCoordinator() { return insertRowsCoordinator; @@ -146,28 +157,6 @@ private ReactiveRemoveCoordinator buildDeleteAllCoordinator() { ); } - @Override - protected CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) { - if ( isCollectionLoaderReusable( loadQueryInfluencers ) ) { - if ( reusableCollectionLoader == null ) { - reusableCollectionLoader = ReactiveAbstractCollectionPersister.super - .generateCollectionLoader( LoadQueryInfluencers.NONE ); - } - return reusableCollectionLoader; - } - - // create a one-off - return ReactiveAbstractCollectionPersister.super.generateCollectionLoader( loadQueryInfluencers ); - } - - @Override - public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers) { - if ( influencers == LoadQueryInfluencers.NONE ) { - return false; - } - return super.isAffectedByEnabledFetchProfiles( influencers ); - } - @Override protected CollectionLoader createSubSelectLoader(SubselectFetch subselect, SharedSessionContractImplementor session) { return new ReactiveCollectionLoaderSubSelectFetch( getAttributeMapping(), null, subselect, session ); @@ -241,7 +230,7 @@ private ReactiveMutationExecutor reactiveMutationExecutor( return (ReactiveMutationExecutor) mutationExecutorService .createExecutor( this::getBasicBatchKey, - new MutationOperationGroupSingle( MutationType.UPDATE, this, updateRowOperation ), + singleOperation( UPDATE, this, updateRowOperation ), session ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java index 770c775e1..2c099df6b 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java @@ -22,7 +22,7 @@ import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.MutationType; -import org.hibernate.sql.model.internal.MutationOperationGroupSingle; +import org.hibernate.sql.model.internal.MutationOperationGroupFactory; import org.hibernate.sql.model.jdbc.JdbcMutationOperation; import static org.hibernate.reactive.util.impl.CompletionStages.loop; @@ -33,7 +33,7 @@ public class ReactiveDeleteRowsCoordinatorStandard extends DeleteRowsCoordinatorStandard implements ReactiveDeleteRowsCoordinator { private final RowMutationOperations rowMutationOperations; private final boolean deleteByIndex; - private MutationOperationGroupSingle operationGroup; + private MutationOperationGroup operationGroup; private final BasicBatchKey batchKey; public ReactiveDeleteRowsCoordinatorStandard( @@ -102,12 +102,12 @@ private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractI .createExecutor( this::getBatchKey, operationGroup, session ); } - private MutationOperationGroupSingle createOperationGroup() { + private MutationOperationGroup createOperationGroup() { assert getMutationTarget().getTargetPart() != null; assert getMutationTarget().getTargetPart().getKeyDescriptor() != null; final JdbcMutationOperation operation = rowMutationOperations.getDeleteRowOperation(); - return new MutationOperationGroupSingle( MutationType.DELETE, getMutationTarget(), operation ); + return MutationOperationGroupFactory.singleOperation( MutationType.DELETE, getMutationTarget(), operation ); } private BasicBatchKey getBatchKey() { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java index 0f0bb29bb..9c941be40 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java @@ -5,7 +5,6 @@ */ package org.hibernate.reactive.persister.collection.mutation; -import java.lang.invoke.MethodHandles; import java.util.Iterator; import java.util.concurrent.CompletionStage; @@ -21,12 +20,13 @@ import org.hibernate.persister.collection.mutation.RowMutationOperations; import org.hibernate.reactive.engine.jdbc.env.internal.ReactiveMutationExecutor; import org.hibernate.reactive.logging.impl.Log; -import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.MutationType; -import org.hibernate.sql.model.internal.MutationOperationGroupSingle; +import org.hibernate.sql.model.internal.MutationOperationGroupFactory; import org.hibernate.sql.model.jdbc.JdbcMutationOperation; +import static java.lang.invoke.MethodHandles.lookup; +import static org.hibernate.reactive.logging.impl.LoggerFactory.make; import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; @@ -37,14 +37,14 @@ */ public class ReactiveInsertRowsCoordinatorStandard implements ReactiveInsertRowsCoordinator { - private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + private static final Log LOG = make( Log.class, lookup() ); private final CollectionMutationTarget mutationTarget; private final RowMutationOperations rowMutationOperations; private final BasicBatchKey batchKey; - private MutationOperationGroupSingle operationGroup; + private MutationOperationGroup operationGroup; public ReactiveInsertRowsCoordinatorStandard(CollectionMutationTarget mutationTarget, RowMutationOperations rowMutationOperations) { this.mutationTarget = mutationTarget; @@ -112,12 +112,12 @@ private BasicBatchKey getBatchKey() { return batchKey; } - private MutationOperationGroupSingle createOperationGroup() { + private MutationOperationGroup createOperationGroup() { assert mutationTarget.getTargetPart() != null; assert mutationTarget.getTargetPart().getKeyDescriptor() != null; final JdbcMutationOperation operation = rowMutationOperations.getInsertRowOperation(); - return new MutationOperationGroupSingle( MutationType.INSERT, mutationTarget, operation ); + return MutationOperationGroupFactory.singleOperation( MutationType.INSERT, mutationTarget, operation ); } private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractImplementor session, MutationOperationGroup operationGroup) { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java index ec4ede1c9..a8d730f7e 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java @@ -23,15 +23,15 @@ import org.hibernate.reactive.util.impl.CompletionStages; import org.hibernate.service.ServiceRegistry; import org.hibernate.sql.model.MutationOperationGroup; -import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.ast.MutatingTableReference; -import org.hibernate.sql.model.internal.MutationOperationGroupSingle; import static org.hibernate.persister.collection.mutation.RowMutationOperations.DEFAULT_RESTRICTOR; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; +import static org.hibernate.sql.model.MutationType.DELETE; +import static org.hibernate.sql.model.internal.MutationOperationGroupFactory.singleOperation; public class ReactiveRemoveCoordinatorStandard extends RemoveCoordinatorStandard implements ReactiveRemoveCoordinator { @@ -39,15 +39,15 @@ public class ReactiveRemoveCoordinatorStandard extends RemoveCoordinatorStandard private final BasicBatchKey batchKey; private final OperationProducer operationProducer; - private MutationOperationGroupSingle operationGroup; + private MutationOperationGroup operationGroup; public ReactiveRemoveCoordinatorStandard( CollectionMutationTarget mutationTarget, OperationProducer operationProducer, ServiceRegistry serviceRegistry) { super( mutationTarget, operationProducer, serviceRegistry ); - this.batchKey = new BasicBatchKey( mutationTarget.getRolePath() + "#REMOVE" ); this.operationProducer = operationProducer; + this.batchKey = new BasicBatchKey( mutationTarget.getRolePath() + "#REMOVE" ); } private BasicBatchKey getBatchKey() { @@ -94,7 +94,7 @@ private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractI } // FIXME: Update ORM and inherit this - protected MutationOperationGroupSingle buildOperationGroup() { + private MutationOperationGroup buildOperationGroup() { assert getMutationTarget().getTargetPart() != null; assert getMutationTarget().getTargetPart().getKeyDescriptor() != null; @@ -105,10 +105,6 @@ protected MutationOperationGroupSingle buildOperationGroup() { final CollectionTableMapping tableMapping = getMutationTarget().getCollectionTableMapping(); final MutatingTableReference tableReference = new MutatingTableReference( tableMapping ); - return new MutationOperationGroupSingle( - MutationType.DELETE, - getMutationTarget(), - operationProducer.createOperation( tableReference ) - ); + return singleOperation( DELETE, getMutationTarget(), operationProducer.createOperation( tableReference ) ); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveUpdateRowsCoordinatorOneToMany.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveUpdateRowsCoordinatorOneToMany.java index d230aa544..99bec6f5a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveUpdateRowsCoordinatorOneToMany.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveUpdateRowsCoordinatorOneToMany.java @@ -5,7 +5,6 @@ */ package org.hibernate.reactive.persister.collection.mutation; -import java.lang.invoke.MethodHandles; import java.util.Iterator; import java.util.concurrent.CompletionStage; @@ -23,24 +22,27 @@ import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorOneToMany; import org.hibernate.reactive.engine.jdbc.env.internal.ReactiveMutationExecutor; import org.hibernate.reactive.logging.impl.Log; -import org.hibernate.reactive.logging.impl.LoggerFactory; import org.hibernate.reactive.util.impl.CompletionStages; -import org.hibernate.sql.model.MutationType; -import org.hibernate.sql.model.internal.MutationOperationGroupSingle; +import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.jdbc.JdbcMutationOperation; +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.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; +import static org.hibernate.sql.model.MutationType.DELETE; +import static org.hibernate.sql.model.MutationType.INSERT; +import static org.hibernate.sql.model.internal.MutationOperationGroupFactory.singleOperation; public class ReactiveUpdateRowsCoordinatorOneToMany extends UpdateRowsCoordinatorOneToMany implements ReactiveUpdateRowsCoordinator{ - private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + private static final Log LOG = make( Log.class, lookup() ); private final RowMutationOperations rowMutationOperations; - private MutationOperationGroupSingle deleteOperationGroup; - private MutationOperationGroupSingle insertOperationGroup; + private MutationOperationGroup deleteOperationGroup; + private MutationOperationGroup insertOperationGroup; public ReactiveUpdateRowsCoordinatorOneToMany(CollectionMutationTarget mutationTarget, RowMutationOperations rowMutationOperations, SessionFactoryImplementor sessionFactory) { super( mutationTarget, rowMutationOperations, sessionFactory ); @@ -80,7 +82,7 @@ private CompletionStage doReactiveUpdate(Object key, PersistentCollecti } private CompletionStage insertRows(Object key, PersistentCollection collection, SharedSessionContractImplementor session) { - final MutationOperationGroupSingle operationGroup = resolveInsertGroup(); + final MutationOperationGroup operationGroup = resolveInsertGroup(); final PluralAttributeMapping attributeMapping = getMutationTarget().getTargetPart(); final CollectionPersister collectionDescriptor = attributeMapping.getCollectionDescriptor(); final ReactiveMutationExecutor mutationExecutor = reactiveMutationExecutor( session, operationGroup, this::getInsertBatchKey ); @@ -119,14 +121,10 @@ private CompletionStage deleteRows( Object key, PersistentCollection collection, SharedSessionContractImplementor session) { - final MutationOperationGroupSingle operationGroup = resolveDeleteGroup(); + final MutationOperationGroup operationGroup = resolveDeleteGroup(); final PluralAttributeMapping attributeMapping = getMutationTarget().getTargetPart(); final CollectionPersister collectionDescriptor = attributeMapping.getCollectionDescriptor(); - final ReactiveMutationExecutor mutationExecutor = reactiveMutationExecutor( - session, - operationGroup, - this::getDeleteBatchKey - ); + final ReactiveMutationExecutor mutationExecutor = reactiveMutationExecutor( session, operationGroup, this::getDeleteBatchKey ); final int[] entryPosition = { -1 }; return voidFuture() @@ -150,7 +148,7 @@ private CompletionStage deleteRows( .thenCompose( CompletionStages::voidFuture ); } - private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractImplementor session, MutationOperationGroupSingle operationGroup, BatchKeyAccess batchKeySupplier) { + private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractImplementor session, MutationOperationGroup operationGroup, BatchKeyAccess batchKeySupplier) { final MutationExecutorService mutationExecutorService = session .getFactory() .getServiceRegistry() @@ -160,12 +158,12 @@ private ReactiveMutationExecutor reactiveMutationExecutor(SharedSessionContractI } //FIXME: Duplicated form ORM - private MutationOperationGroupSingle resolveDeleteGroup() { + private MutationOperationGroup resolveDeleteGroup() { if ( deleteOperationGroup == null ) { final JdbcMutationOperation operation = rowMutationOperations.getDeleteRowOperation(); assert operation != null; - deleteOperationGroup = new MutationOperationGroupSingle( MutationType.DELETE, getMutationTarget(), operation ); + deleteOperationGroup = singleOperation( DELETE, getMutationTarget(), operation ); } return deleteOperationGroup; @@ -173,12 +171,12 @@ private MutationOperationGroupSingle resolveDeleteGroup() { //FIXME: Duplicated from ORM - private MutationOperationGroupSingle resolveInsertGroup() { + private MutationOperationGroup resolveInsertGroup() { if ( insertOperationGroup == null ) { final JdbcMutationOperation operation = rowMutationOperations.getInsertRowOperation(); assert operation != null; - insertOperationGroup = new MutationOperationGroupSingle( MutationType.INSERT, getMutationTarget(), operation ); + insertOperationGroup = singleOperation( INSERT, getMutationTarget(), operation ); } return insertOperationGroup; 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 671dbd0b4..461164b3c 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 @@ -261,10 +261,14 @@ default Object nextVersionForLock(LockMode lockMode, Object id, Object currentVe @Override default CompletionStage reactiveGetDatabaseSnapshot(Object id, SharedSessionContractImplementor session) { - return getReactiveSingleIdEntityLoader().reactiveLoadDatabaseSnapshot( id, session ); + ReactiveSingleIdEntityLoader reactiveSingleIdEntityLoader = getReactiveSingleIdEntityLoader(); + return reactiveSingleIdEntityLoader.reactiveLoadDatabaseSnapshot( id, session ); } - ReactiveSingleIdEntityLoader getReactiveSingleIdEntityLoader(); + default ReactiveSingleIdEntityLoader getReactiveSingleIdEntityLoader() { + AbstractEntityPersister delegate = delegate(); + return (ReactiveSingleIdEntityLoader) delegate.getSingleIdLoader(); + } /** * @see AbstractEntityPersister#getCurrentVersion(Object, SharedSessionContractImplementor) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractPersisterDelegate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractPersisterDelegate.java index cd7a944b5..fe58ba434 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractPersisterDelegate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveAbstractPersisterDelegate.java @@ -11,10 +11,12 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; import org.hibernate.FetchMode; import org.hibernate.LockOptions; import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.event.spi.EventSource; @@ -38,6 +40,7 @@ import org.hibernate.pretty.MessageHelper; import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.query.named.NamedQueryMemento; +import org.hibernate.reactive.loader.ast.internal.ReactiveMultiIdEntityLoaderArrayParam; import org.hibernate.reactive.loader.ast.internal.ReactiveMultiIdEntityLoaderStandard; import org.hibernate.reactive.loader.ast.internal.ReactiveSingleIdEntityLoaderProvidedQueryImpl; import org.hibernate.reactive.loader.ast.internal.ReactiveSingleIdEntityLoaderStandardImpl; @@ -55,8 +58,10 @@ import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultCreationState; +import org.hibernate.type.BasicType; import org.hibernate.type.EntityType; +import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.supportsSqlArrayType; import static org.hibernate.pretty.MessageHelper.infoString; /** @@ -66,8 +71,11 @@ public class ReactiveAbstractPersisterDelegate { private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final ReactiveSingleIdEntityLoader singleIdEntityLoader; - private final ReactiveMultiIdEntityLoader multiIdEntityLoader; + private final Supplier> singleIdEntityLoaderSupplier; + private final Supplier> multiIdEntityLoaderSupplier; + + private ReactiveSingleIdEntityLoader singleIdEntityLoader; + private ReactiveMultiIdEntityLoader multiIdEntityLoader; private final EntityPersister entityDescriptor; @@ -78,21 +86,20 @@ public ReactiveAbstractPersisterDelegate( final PersistentClass persistentClass, final RuntimeModelCreationContext creationContext) { SessionFactoryImplementor factory = creationContext.getSessionFactory(); - singleIdEntityLoader = createReactiveSingleIdEntityLoader( - entityPersister, - persistentClass, - creationContext, - factory, - entityPersister.getEntityName() - ); - multiIdEntityLoader = new ReactiveMultiIdEntityLoaderStandard<>( entityPersister, persistentClass, factory ); + singleIdEntityLoaderSupplier = () -> buildSingleIdEntityLoader( entityPersister, persistentClass, creationContext, factory, entityPersister.getEntityName() ); + multiIdEntityLoaderSupplier = () -> buildMultiIdEntityLoader( entityPersister, persistentClass, factory ); entityDescriptor = entityPersister; } - public ReactiveSingleIdEntityLoader getSingleIdEntityLoader() { + public ReactiveSingleIdEntityLoader buildSingleIdEntityLoader() { + singleIdEntityLoader = singleIdEntityLoaderSupplier.get(); return singleIdEntityLoader; } + public ReactiveMultiIdEntityLoader buildMultiIdEntityLoader() { + multiIdEntityLoader = multiIdEntityLoaderSupplier.get(); + return multiIdEntityLoader; + } public DomainResult createDomainResult( EntityValuedModelPart assemblerCreationState, @@ -109,35 +116,42 @@ public DomainResult createDomainResult( /** * @see org.hibernate.persister.entity.AbstractEntityPersister#multiLoad(Object[], EventSource, MultiIdLoadOptions)` */ - public CompletionStage> multiLoad( - K[] ids, - EventSource session, - MultiIdLoadOptions loadOptions) { - return multiIdEntityLoader.load( ids, loadOptions, session ); + public CompletionStage> multiLoad(K[] ids, EventSource session, MultiIdLoadOptions loadOptions) { + return multiIdEntityLoader.reactiveLoad( ids, loadOptions, session ); } - private static ReactiveSingleIdEntityLoader createReactiveSingleIdEntityLoader( - EntityMappingType entityDescriptor, + private static ReactiveMultiIdEntityLoader buildMultiIdEntityLoader( + EntityPersister entityDescriptor, + PersistentClass persistentClass, + SessionFactoryImplementor factory) { + return entityDescriptor.getIdentifierType() instanceof BasicType + && supportsSqlArrayType( factory.getJdbcServices().getDialect() ) + ? new ReactiveMultiIdEntityLoaderArrayParam<>( entityDescriptor, factory ) + : new ReactiveMultiIdEntityLoaderStandard<>( entityDescriptor, persistentClass, factory ); + } + + private static ReactiveSingleIdEntityLoader buildSingleIdEntityLoader( + EntityPersister entityDescriptor, PersistentClass bootDescriptor, RuntimeModelCreationContext creationContext, SessionFactoryImplementor factory, String entityName) { - int batchSize = batchSize( bootDescriptor, factory ); if ( bootDescriptor.getLoaderName() != null ) { // We must resolve the named query on-demand through the boot model because it isn't initialized yet - final NamedQueryMemento namedQueryMemento = factory.getQueryEngine().getNamedObjectRepository().resolve( - factory, - creationContext.getBootModel(), - bootDescriptor.getLoaderName() - ); + final NamedQueryMemento namedQueryMemento = factory.getQueryEngine().getNamedObjectRepository() + .resolve( factory, creationContext.getBootModel(), bootDescriptor.getLoaderName() ); if ( namedQueryMemento == null ) { throw new IllegalArgumentException( "Could not resolve named load-query [" + entityName + "] : " + bootDescriptor.getLoaderName() ); } return new ReactiveSingleIdEntityLoaderProvidedQueryImpl<>( entityDescriptor, namedQueryMemento ); } - if ( batchSize > 1 ) { - return createBatchingIdEntityLoader( entityDescriptor, batchSize, factory ); + LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( factory ); + if ( loadQueryInfluencers.effectivelyBatchLoadable( entityDescriptor ) ) { + final int batchSize = loadQueryInfluencers.effectiveBatchSize( entityDescriptor ); + if ( batchSize > 1 ) { + return createBatchingIdEntityLoader( entityDescriptor, batchSize, factory ); + } } return new ReactiveSingleIdEntityLoaderStandardImpl<>( entityDescriptor, factory ); @@ -152,14 +166,6 @@ private static ReactiveSingleIdEntityLoader createBatchingIdEntityLoader .createEntityBatchLoader( domainBatchSize, entityDescriptor, factory ); } - private static int batchSize(PersistentClass bootDescriptor, SessionFactoryImplementor factory) { - int batchSize = bootDescriptor.getBatchSize(); - if ( batchSize == -1 ) { - batchSize = factory.getSessionFactoryOptions().getDefaultBatchFetchSize(); - } - return batchSize; - } - public CompletionStage processInsertGeneratedProperties( Object id, Object entity, @@ -214,10 +220,7 @@ protected ReactiveSingleUniqueKeyEntityLoader getReactiveUniqueKeyLoader } return uniqueKeyLoadersNew.computeIfAbsent( attribute, - key -> new ReactiveSingleUniqueKeyEntityLoaderStandard<>( - entityDescriptor, - key - ) + key -> new ReactiveSingleUniqueKeyEntityLoaderStandard<>( entityDescriptor, key ) ); } @@ -249,10 +252,8 @@ public CompletionStage loadEntityIdByNaturalId( ); } - return ( (ReactiveNaturalIdLoader) entityDescriptor.getNaturalIdLoader() ).resolveNaturalIdToId( - orderedNaturalIdValues, - session - ); + return ( (ReactiveNaturalIdLoader) entityDescriptor.getNaturalIdLoader() ) + .resolveNaturalIdToId( orderedNaturalIdValues, session ); } public AttributeMapping buildSingularAssociationAttributeMapping( 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 ec8ea7800..53150443d 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 @@ -17,7 +17,9 @@ import org.hibernate.event.spi.EventSource; import org.hibernate.generator.Generator; import org.hibernate.jdbc.Expectation; +import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.ast.spi.SingleIdEntityLoader; import org.hibernate.loader.ast.spi.SingleUniqueKeyEntityLoader; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; @@ -36,7 +38,6 @@ import org.hibernate.persister.entity.mutation.UpdateCoordinator; import org.hibernate.reactive.loader.ast.internal.ReactiveSingleIdArrayLoadPlan; import org.hibernate.property.access.spi.PropertyAccess; -import org.hibernate.reactive.loader.ast.spi.ReactiveSingleIdEntityLoader; import org.hibernate.reactive.loader.ast.spi.ReactiveSingleUniqueKeyEntityLoader; import org.hibernate.reactive.persister.entity.mutation.ReactiveDeleteCoordinator; import org.hibernate.reactive.persister.entity.mutation.ReactiveInsertCoordinator; @@ -73,6 +74,15 @@ public ReactiveJoinedSubclassEntityPersister( reactiveDelegate = new ReactiveAbstractPersisterDelegate( this, persistentClass, creationContext ); } + @Override + protected SingleIdEntityLoader buildSingleIdEntityLoader() { + return reactiveDelegate.buildSingleIdEntityLoader(); + } + + @Override + protected MultiIdEntityLoader buildMultiIdLoader() { + return reactiveDelegate.buildMultiIdEntityLoader(); + } @Override protected AttributeMapping buildSingularAssociationAttributeMapping( @@ -152,11 +162,6 @@ public Generator getGenerator() throws HibernateException { return reactiveDelegate.reactive( super.getGenerator() ); } - @Override - public ReactiveSingleIdEntityLoader getReactiveSingleIdEntityLoader() { - return reactiveDelegate.getSingleIdEntityLoader(); - } - @Override public DomainResult createDomainResult( NavigablePath navigablePath, 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 a8f36a714..8d2291731 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 @@ -21,7 +21,9 @@ import org.hibernate.event.spi.EventSource; import org.hibernate.generator.Generator; import org.hibernate.jdbc.Expectation; +import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.ast.spi.SingleIdEntityLoader; import org.hibernate.loader.ast.spi.SingleUniqueKeyEntityLoader; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; @@ -40,7 +42,6 @@ import org.hibernate.persister.entity.mutation.UpdateCoordinator; import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.reactive.loader.ast.internal.ReactiveSingleIdArrayLoadPlan; -import org.hibernate.reactive.loader.ast.spi.ReactiveSingleIdEntityLoader; import org.hibernate.reactive.loader.ast.spi.ReactiveSingleUniqueKeyEntityLoader; import org.hibernate.reactive.persister.entity.mutation.ReactiveDeleteCoordinator; import org.hibernate.reactive.persister.entity.mutation.ReactiveInsertCoordinator; @@ -59,7 +60,7 @@ */ public class ReactiveSingleTableEntityPersister extends SingleTableEntityPersister implements ReactiveAbstractEntityPersister { - private final ReactiveAbstractPersisterDelegate reactiveDelegate; + private ReactiveAbstractPersisterDelegate reactiveDelegate; public ReactiveSingleTableEntityPersister( final PersistentClass persistentClass, @@ -70,6 +71,16 @@ public ReactiveSingleTableEntityPersister( reactiveDelegate = new ReactiveAbstractPersisterDelegate( this, persistentClass, creationContext ); } + @Override + protected SingleIdEntityLoader buildSingleIdEntityLoader() { + return reactiveDelegate.buildSingleIdEntityLoader(); + } + + @Override + protected MultiIdEntityLoader buildMultiIdLoader() { + return reactiveDelegate.buildMultiIdEntityLoader(); + } + @Override public String generateSelectVersionString() { String sql = super.generateSelectVersionString(); @@ -177,11 +188,6 @@ public String[][] getLazyPropertyColumnAliases() { return super.getLazyPropertyColumnAliases(); } - @Override - public ReactiveSingleIdEntityLoader getReactiveSingleIdEntityLoader() { - return reactiveDelegate.getSingleIdEntityLoader(); - } - @Override public Object insert(Object[] fields, Object object, SharedSessionContractImplementor session) { throw LOG.nonReactiveMethodCall( "insertReactive" ); 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 64023c18b..2269173da 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 @@ -24,7 +24,9 @@ import org.hibernate.generator.Generator; import org.hibernate.id.IdentityGenerator; import org.hibernate.jdbc.Expectation; +import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; +import org.hibernate.loader.ast.spi.SingleIdEntityLoader; import org.hibernate.loader.ast.spi.SingleUniqueKeyEntityLoader; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; @@ -43,7 +45,6 @@ import org.hibernate.persister.entity.mutation.UpdateCoordinator; import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.reactive.loader.ast.internal.ReactiveSingleIdArrayLoadPlan; -import org.hibernate.reactive.loader.ast.spi.ReactiveSingleIdEntityLoader; import org.hibernate.reactive.loader.ast.spi.ReactiveSingleUniqueKeyEntityLoader; import org.hibernate.reactive.logging.impl.Log; import org.hibernate.reactive.logging.impl.LoggerFactory; @@ -76,6 +77,16 @@ public ReactiveUnionSubclassEntityPersister( reactiveDelegate = new ReactiveAbstractPersisterDelegate( this, persistentClass, creationContext ); } + @Override + protected SingleIdEntityLoader buildSingleIdEntityLoader() { + return reactiveDelegate.buildSingleIdEntityLoader(); + } + + @Override + protected MultiIdEntityLoader buildMultiIdLoader() { + return reactiveDelegate.buildMultiIdEntityLoader(); + } + @Override protected AttributeMapping buildSingularAssociationAttributeMapping( String attrName, @@ -175,11 +186,6 @@ public Generator getGenerator() throws HibernateException { return reactiveDelegate.reactive( super.getGenerator() ); } - @Override - public ReactiveSingleIdEntityLoader getReactiveSingleIdEntityLoader() { - return reactiveDelegate.getSingleIdEntityLoader(); - } - @Override public String[][] getLazyPropertyColumnAliases() { return super.getLazyPropertyColumnAliases(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/ReactivePersistenceProvider.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/ReactivePersistenceProvider.java index b68e4c6e3..df25197b2 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/ReactivePersistenceProvider.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/ReactivePersistenceProvider.java @@ -9,11 +9,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import jakarta.persistence.EntityManagerFactory; -import jakarta.persistence.spi.LoadState; -import jakarta.persistence.spi.PersistenceProvider; -import jakarta.persistence.spi.PersistenceUnitInfo; -import jakarta.persistence.spi.ProviderUtil; import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; @@ -26,8 +21,16 @@ import org.hibernate.reactive.provider.impl.ReactiveEntityManagerFactoryBuilder; import org.hibernate.reactive.provider.impl.ReactiveProviderChecker; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.spi.LoadState; +import jakarta.persistence.spi.PersistenceProvider; +import jakarta.persistence.spi.PersistenceUnitInfo; +import jakarta.persistence.spi.ProviderUtil; + /** - * JPA {@link PersistenceProvider} for Hibernate Reactive. + * A JPA {@link PersistenceProvider} for Hibernate Reactive. + * + * @see org.hibernate.jpa.HibernatePersistenceProvider */ public class ReactivePersistenceProvider implements PersistenceProvider { @@ -43,19 +46,22 @@ public class ReactivePersistenceProvider implements PersistenceProvider { @Override public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) { log.tracef( "Starting createEntityManagerFactory for persistenceUnitName %s", persistenceUnitName ); - final Map immutableProperties = immutable( properties ); + final Map immutableProperties = immutable( properties ); final EntityManagerFactoryBuilder builder = getEntityManagerFactoryBuilderOrNull( persistenceUnitName, immutableProperties ); if ( builder == null ) { log.trace( "Could not obtain matching EntityManagerFactoryBuilder, returning null" ); return null; } - else { - return builder.build(); - } + return builder.build(); } - protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties) { - log.tracef( "Attempting to obtain correct EntityManagerFactoryBuilder for persistenceUnitName : %s", persistenceUnitName ); + protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull( + String persistenceUnitName, + Map properties) { + log.tracef( + "Attempting to obtain correct EntityManagerFactoryBuilder for persistenceUnitName : %s", + persistenceUnitName + ); final List units; try { @@ -80,14 +86,15 @@ protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(Strin persistenceUnitName ); - final boolean matches = persistenceUnitName == null || persistenceUnit.getName().equals( persistenceUnitName ); + final boolean matches = persistenceUnitName == null || persistenceUnit.getName() + .equals( persistenceUnitName ); if ( !matches ) { log.debug( "Excluding from consideration due to name mis-match" ); continue; } // See if we (Hibernate Reactive) are the persistence provider - if ( ! ReactiveProviderChecker.isProvider( persistenceUnit, properties ) ) { + if ( !ReactiveProviderChecker.isProvider( persistenceUnit, properties ) ) { log.debug( "Excluding from consideration due to provider mis-match" ); continue; } @@ -99,8 +106,7 @@ protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(Strin return null; } - @SuppressWarnings("unchecked") - private static Map immutable(Map properties) { + private static Map immutable(Map properties) { return properties == null ? Collections.emptyMap() : Collections.unmodifiableMap( properties ); } @@ -137,11 +143,11 @@ public boolean generateSchema(String persistenceUnitName, Map map) { return true; } - protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitInfo info, Map integration) { + protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitInfo info, Map integration) { return getEntityManagerFactoryBuilder( new PersistenceUnitInfoDescriptor( info ), integration ); } - protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitDescriptor persistenceUnitDescriptor, Map integration) { + protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitDescriptor persistenceUnitDescriptor, Map integration) { return new ReactiveEntityManagerFactoryBuilder( persistenceUnitDescriptor, integration ); } @@ -150,13 +156,15 @@ protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(Persistence public LoadState isLoadedWithoutReference(Object proxy, String property) { return PersistenceUtilHelper.isLoadedWithoutReference( proxy, property, cache ); } + @Override public LoadState isLoadedWithReference(Object proxy, String property) { return PersistenceUtilHelper.isLoadedWithReference( proxy, property, cache ); } + @Override public LoadState isLoaded(Object o) { - return PersistenceUtilHelper.isLoaded(o); + return PersistenceUtilHelper.getLoadState( o ); } }; diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveTypeContributor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveTypeContributor.java index f1a6bc7dc..7a111e43b 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveTypeContributor.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/impl/ReactiveTypeContributor.java @@ -44,6 +44,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; import org.hibernate.type.descriptor.jdbc.ObjectJdbcType; +import org.hibernate.type.descriptor.jdbc.ReactiveArrayJdbcTypeConstructor; import org.hibernate.type.descriptor.jdbc.TimestampJdbcType; import org.hibernate.type.descriptor.jdbc.TimestampUtcAsJdbcTimestampJdbcType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; @@ -82,6 +83,7 @@ private void registerReactiveChanges(TypeContributions typeContributions, Servic JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration.getJdbcTypeRegistry(); jdbcTypeRegistry.addDescriptor( ReactiveArrayJdbcType.INSTANCE ); + jdbcTypeRegistry.addTypeConstructor( ReactiveArrayJdbcTypeConstructor.INSTANCE ); if ( dialect instanceof MySQLDialect || dialect instanceof DB2Dialect || dialect instanceof OracleDialect ) { jdbcTypeRegistry.addDescriptor( TimestampAsLocalDateTimeJdbcType.INSTANCE ); @@ -188,11 +190,6 @@ public String getRawTypeName() { return "json"; } - @Override - public String getTypeNamePattern() { - return ""; - } - @Override public String getTypeName(Long size, Integer precision, Integer scale) { return "json"; diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java index 15ecbea72..6bf2f47a8 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java @@ -60,7 +60,7 @@ public class ReactiveAbstractSelectionQuery { private final Supplier getDomainParameterXref; - private final Supplier> getResultType; + private final Supplier> getResultType; private final Supplier getQueryString; private final Runnable beforeQuery; @@ -78,7 +78,7 @@ public ReactiveAbstractSelectionQuery( Supplier> getStatement, Supplier getTupleMetadata, Supplier getDomainParameterXref, - Supplier> getResultType, + Supplier> getResultType, Supplier getQueryString, Runnable beforeQuery, Consumer afterQuery, @@ -106,7 +106,7 @@ public ReactiveAbstractSelectionQuery( Supplier> getStatement, Supplier getTupleMetadata, Supplier getDomainParameterXref, - Supplier> getResultType, + Supplier> getResultType, Supplier getQueryString, Runnable beforeQuery, Consumer afterQuery, @@ -264,8 +264,8 @@ private CompletionStage> doReactiveList() { return doList.get(); } - public SqmStatement getSqmStatement() { - return getStatement.get(); + public SqmStatement getSqmStatement() { + return (SqmStatement) getStatement.get(); } public TupleMetadata getTupleMetadata() { @@ -273,7 +273,7 @@ public TupleMetadata getTupleMetadata() { } public Class getResultType() { - return getResultType.get(); + return (Class) getResultType.get(); } public DomainParameterXref getDomainParameterXref() { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java index e8a990382..3165b886e 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java @@ -193,7 +193,7 @@ private CompletionStage> doReactiveList() { final boolean needsDistinct = containsCollectionFetches && ( sqmStatement.usesDistinct() || hasAppliedGraph( getQueryOptions() ) || hasLimit ); - final DomainQueryExecutionContext executionContextToUse = executionContextFordoList( containsCollectionFetches, hasLimit, needsDistinct ); + final DomainQueryExecutionContext executionContextToUse = executionContextForDoList( containsCollectionFetches, hasLimit, needsDistinct ); return resolveSelectReactiveQueryPlan() .reactivePerformList( executionContextToUse ) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java index 42b11a316..685599037 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java @@ -93,7 +93,7 @@ private CompletionStage> doReactiveList() { getSession().prepareForQueryExecution( requiresTxn( getQueryOptions().getLockOptions() .findGreatestLockMode() ) ); - final SqmSelectStatement sqmStatement = (SqmSelectStatement) getSqmStatement(); + final SqmSelectStatement sqmStatement = getSqmStatement(); final boolean containsCollectionFetches = sqmStatement.containsCollectionFetches(); final boolean hasLimit = hasLimit( sqmStatement, getQueryOptions() ); final boolean needsDistinct = containsCollectionFetches 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 635b5cb76..3b8fe2b2c 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 @@ -209,7 +209,7 @@ default Expression createCountStar( return factory.getQueryEngine() .getSqmFunctionRegistry() .findFunctionDescriptor( "count" ) - .generateSqmExpression( arg, null, factory.getQueryEngine(), typeConfiguration ) + .generateSqmExpression( arg, null, factory.getQueryEngine() ) .convertToSqlAst( sqmConverter ); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionFactoryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionFactoryImpl.java index 4f11aa949..85c921c7c 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionFactoryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/impl/ReactiveSessionFactoryImpl.java @@ -5,8 +5,6 @@ */ package org.hibernate.reactive.session.impl; - - import org.hibernate.boot.spi.BootstrapContext; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.SessionFactoryOptions; @@ -19,8 +17,6 @@ import org.hibernate.reactive.stage.Stage; import org.hibernate.reactive.stage.impl.StageSessionFactoryImpl; - - /** * A Hibernate {@link org.hibernate.SessionFactory} that can be * unwrapped to produce a {@link Stage.SessionFactory} or a 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 fc03aa27e..bafbcad61 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 @@ -7,7 +7,6 @@ import java.lang.invoke.MethodHandles; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletionException; @@ -68,21 +67,13 @@ import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.query.IllegalMutationQueryException; -import org.hibernate.query.IllegalNamedQueryOptionsException; -import org.hibernate.query.IllegalSelectQueryException; -import org.hibernate.query.QueryTypeMismatchException; import org.hibernate.query.criteria.JpaCriteriaInsertSelect; import org.hibernate.query.hql.spi.SqmQueryImplementor; import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.spi.HqlInterpretation; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryImplementor; -import org.hibernate.query.sql.spi.NamedNativeQueryMemento; import org.hibernate.query.sql.spi.NativeQueryImplementor; -import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl; import org.hibernate.query.sqm.internal.SqmUtil; -import org.hibernate.query.sqm.spi.NamedSqmQueryMemento; -import org.hibernate.query.sqm.tree.SqmDmlStatement; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement; @@ -135,9 +126,6 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.spi.NaturalIdResolutions.INVALID_NATURAL_ID_REFERENCE; import static org.hibernate.event.spi.LoadEventListener.IMMEDIATE_LOAD; -import static org.hibernate.event.spi.LoadEventListener.INTERNAL_LOAD_EAGER; -import static org.hibernate.event.spi.LoadEventListener.INTERNAL_LOAD_LAZY; -import static org.hibernate.event.spi.LoadEventListener.INTERNAL_LOAD_NULLABLE; import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; @@ -243,7 +231,7 @@ public CompletionStage reactiveInternalLoad(String entityName, Object id final GraphSemantic semantic = effectiveEntityGraph.getSemantic(); final RootGraphImplementor graph = effectiveEntityGraph.getGraph(); boolean clearedEffectiveGraph; - if ( semantic == null || graph.appliesTo( entityName ) ) { + if ( semantic == null || graph.appliesTo( getFactory().getJpaMetamodel().entity( entityName ) ) ) { clearedEffectiveGraph = false; } else { @@ -272,16 +260,6 @@ public CompletionStage reactiveInternalLoad(String entityName, Object id } ); } - //TODO: deleteme, use inherited version - private static LoadEventListener.LoadType internalLoadType(boolean eager, boolean nullable) { - if ( nullable ) { - return INTERNAL_LOAD_NULLABLE; - } - else { - return eager ? INTERNAL_LOAD_EAGER : INTERNAL_LOAD_LAZY; - } - } - @Override //Note: when making changes to this method, please also consider // the similar code in Mutiny.fetch() and Stage.fetch() @@ -400,16 +378,6 @@ public ReactiveQuery createReactiveQuery(String queryString, Class exp } } - private HqlInterpretation interpretHql(String hql, Class resultType) { - final QueryEngine queryEngine = getFactory().getQueryEngine(); - return queryEngine.getInterpretationCache() - .resolveHqlInterpretation( - hql, - resultType, - s -> queryEngine.getHqlTranslator().translate( hql, resultType ) - ); - } - @Override public ReactiveNativeQueryImplementor createReactiveNativeQuery(String sqlString) { checkOpen(); @@ -536,26 +504,6 @@ private ReactiveSelectionQuery createSelectionQuery(String hql, Class return query; } - private static void checkSelectionQuery(String hql, HqlInterpretation hqlInterpretation) { - if ( !( hqlInterpretation.getSqmStatement() instanceof SqmSelectStatement ) ) { - throw new IllegalSelectQueryException( "Expecting a selection query, but found `" + hql + "`", hql); - } - } - - private static void checkResultType(Class expectedResultType, SqmSelectionQueryImpl query) { - final Class resultType = query.getResultType(); - if ( !expectedResultType.isAssignableFrom( resultType ) ) { - throw new QueryTypeMismatchException( - String.format( - Locale.ROOT, - "Query result-type error - expecting `%s`, but found `%s`", - expectedResultType.getName(), - resultType.getName() - ) - ); - } - } - @Override public ReactiveQueryImplementor createReactiveNamedQuery(String name, Class resultType) { return (ReactiveQueryImplementor) buildNamedQuery( name, resultType ); @@ -575,13 +523,6 @@ public ReactiveMutationQuery createReactiveMutationQuery(String hqlString return new ReactiveQuerySqmImpl<>( sqmStatement, null, this ); } - // Change visibility in ORM - private static void checkMutationQuery(String hqlString, SqmStatement sqmStatement) { - if ( !( sqmStatement instanceof SqmDmlStatement ) ) { - throw new IllegalMutationQueryException( "Expecting a mutation query, but found `" + hqlString + "`" ); - } - } - @Override public ReactiveMutationQuery createReactiveMutationQuery(CriteriaUpdate updateQuery) { checkOpen(); @@ -624,44 +565,6 @@ public ReactiveMutationQuery createNamedReactiveMutationQuery(String quer ); } - // Copy and paste from ORM: change the visibility instead - private NativeQueryImplementor createNativeQueryImplementor(String queryName, NamedNativeQueryMemento memento) { - final NativeQueryImplementor query = memento.toQuery( this ); - final Boolean isUnequivocallySelect = query.isSelectQuery(); - if ( isUnequivocallySelect == TRUE ) { - throw new IllegalMutationQueryException( - "Expecting named native query (" + queryName + ") to be a mutation query, but found `" - + memento.getSqlString() + "`" - ); - } - if ( isEmpty( query.getComment() ) ) { - query.setComment( "dynamic native-SQL query" ); - } - applyQuerySettingsAndHints( query ); - return query; - } - - // Copy and paste from ORM: change the visibility instead - private SqmQueryImplementor createSqmQueryImplementor(String queryName, NamedSqmQueryMemento memento) { - final SqmQueryImplementor query = memento.toQuery( this ); - final SqmStatement sqmStatement = query.getSqmStatement(); - if ( !( sqmStatement instanceof SqmDmlStatement ) ) { - throw new IllegalMutationQueryException( - "Expecting a named mutation query (" + queryName + "), but found a select statement" - ); - } - if ( memento.getLockOptions() != null && ! memento.getLockOptions().isEmpty() ) { - throw new IllegalNamedQueryOptionsException( - "Named mutation query `" + queryName + "` specified lock-options" - ); - } - if ( isEmpty( query.getComment() ) ) { - query.setComment( "dynamic HQL query" ); - } - applyQuerySettingsAndHints( query ); - return query; - } - @Override public ReactiveSelectionQuery createNamedReactiveSelectionQuery(String queryName) { return (ReactiveSelectionQuery) createNamedSelectionQuery( queryName, null ); @@ -769,16 +672,6 @@ public Class getResultType() { }; } - //TODO: deleteme, call superclass method - private NamedResultSetMappingMemento getResultSetMappingMemento(String resultSetMappingName) { - final NamedResultSetMappingMemento resultSetMappingMemento = getFactory() - .getQueryEngine().getNamedObjectRepository().getResultSetMappingMemento( resultSetMappingName ); - if ( resultSetMappingMemento == null ) { - throw new HibernateException( "Could not resolve specified result-set mapping name: " + resultSetMappingName ); - } - return resultSetMappingMemento; - } - /** * @deprecated use {@link #reactiveInitializeCollection(PersistentCollection, boolean)} instead */ @@ -1692,8 +1585,8 @@ protected void performAnyNeededCrossReferenceSynchronizations() { } } - protected final ReactiveIdentifierLoadAccessImpl getIdentifierLoadAccess() { - final ReactiveIdentifierLoadAccessImpl identifierLoadAccess = new ReactiveIdentifierLoadAccessImpl( + protected final ReactiveIdentifierLoadAccessImpl getIdentifierLoadAccess() { + final ReactiveIdentifierLoadAccessImpl identifierLoadAccess = new ReactiveIdentifierLoadAccessImpl<>( entityPersister ); if ( this.lockOptions != null ) { identifierLoadAccess.with( lockOptions ); 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 198fbd101..afd7b2e5a 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 @@ -6,7 +6,6 @@ package org.hibernate.reactive.session.impl; import java.lang.invoke.MethodHandles; -import java.util.Locale; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -40,22 +39,14 @@ import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.query.IllegalMutationQueryException; -import org.hibernate.query.IllegalNamedQueryOptionsException; -import org.hibernate.query.IllegalSelectQueryException; -import org.hibernate.query.QueryTypeMismatchException; import org.hibernate.query.criteria.JpaCriteriaInsertSelect; import org.hibernate.query.hql.spi.SqmQueryImplementor; import org.hibernate.query.named.NamedResultSetMappingMemento; import org.hibernate.query.spi.HqlInterpretation; -import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryImplementor; import org.hibernate.query.sql.internal.NativeQueryImpl; -import org.hibernate.query.sql.spi.NamedNativeQueryMemento; import org.hibernate.query.sql.spi.NativeQueryImplementor; -import org.hibernate.query.sqm.internal.SqmSelectionQueryImpl; import org.hibernate.query.sqm.internal.SqmUtil; -import org.hibernate.query.sqm.spi.NamedSqmQueryMemento; -import org.hibernate.query.sqm.tree.SqmDmlStatement; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement; @@ -617,12 +608,9 @@ else if ( isPersistentAttributeInterceptable( association ) ) { } } - @Override public RootGraphImplementor createEntityGraph(Class entity) { - return new RootGraphImpl<>( null, - getFactory().getJpaMetamodel().entity( entity ), - getSessionFactory().getJpaMetamodel() ); + return new RootGraphImpl<>( null, getFactory().getJpaMetamodel().entity( entity ) ); } @Override @@ -635,14 +623,6 @@ public RootGraphImplementor createEntityGraph(Class entity, String nam return (RootGraphImplementor) entityGraph; } - private RootGraphImplementor createEntityGraph(String graphName) { - checkOpen(); - final RootGraphImplementor named = getFactory().findEntityGraphByName( graphName ); - return named != null - ? named.makeRootGraph( graphName, true ) - : null; - } - @Override @SuppressWarnings("unchecked") public RootGraphImplementor getEntityGraph(Class entity, String name) { @@ -653,15 +633,6 @@ public RootGraphImplementor getEntityGraph(Class entity, String name) return (RootGraphImplementor) entityGraph; } - private RootGraphImplementor getEntityGraph(String graphName) { - checkOpen(); - final RootGraphImplementor named = getFactory().findEntityGraphByName( graphName ); - if ( named == null ) { - throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName ); - } - return named; - } - @Override public ReactiveSqmQueryImplementor createReactiveQuery(String queryString) { return createReactiveQuery( queryString, null ); @@ -732,17 +703,6 @@ public ReactiveSqmQueryImplementor createReactiveQuery(String queryString } } - // TODO: copy and paste from ORM: change the visibility instead - private HqlInterpretation interpretHql(String hql, Class resultType) { - final QueryEngine queryEngine = getFactory().getQueryEngine(); - return queryEngine.getInterpretationCache() - .resolveHqlInterpretation( - hql, - resultType, - s -> queryEngine.getHqlTranslator().translate( hql, resultType ) - ); - } - @Override public ReactiveNativeQueryImplementor createReactiveNativeQuery(String sqlString) { checkOpen(); @@ -868,28 +828,6 @@ private ReactiveSelectionQuery createSelectionQuery(String hql, Class return query; } - // TODO: copy and paste from ORM: change the visibility instead - private static void checkSelectionQuery(String hql, HqlInterpretation hqlInterpretation) { - if ( !( hqlInterpretation.getSqmStatement() instanceof SqmSelectStatement ) ) { - throw new IllegalSelectQueryException( "Expecting a selection query, but found `" + hql + "`", hql); - } - } - - // TODO: copy and paste from ORM: change the visibility instead - private static void checkResultType(Class expectedResultType, SqmSelectionQueryImpl query) { - final Class resultType = query.getResultType(); - if ( !expectedResultType.isAssignableFrom( resultType ) ) { - throw new QueryTypeMismatchException( - String.format( - Locale.ROOT, - "Query result-type error - expecting `%s`, but found `%s`", - expectedResultType.getName(), - resultType.getName() - ) - ); - } - } - @Override public ReactiveSelectionQuery createReactiveSelectionQuery(CriteriaQuery criteria) { SqmUtil.verifyIsSelectStatement( (SqmStatement) criteria, null ); @@ -904,13 +842,6 @@ public ReactiveMutationQuery createReactiveMutationQuery(String hqlString return new ReactiveQuerySqmImpl<>( sqmStatement, null, this ); } - //TODO: change visibility in ORM - private static void checkMutationQuery(String hqlString, SqmStatement sqmStatement) { - if ( !( sqmStatement instanceof SqmDmlStatement ) ) { - throw new IllegalMutationQueryException( "Expecting a mutation query, but found `" + hqlString + "`" ); - } - } - @Override public ReactiveMutationQuery createReactiveMutationQuery(CriteriaUpdate updateQuery) { checkOpen(); @@ -958,44 +889,6 @@ public ReactiveMutationQuery createNamedReactiveMutationQuery(String quer ); } - // TODO: copy and paste from ORM: change the visibility instead - private NativeQueryImplementor createNativeQueryImplementor(String queryName, NamedNativeQueryMemento memento) { - final NativeQueryImplementor query = memento.toQuery( this ); - final Boolean isUnequivocallySelect = query.isSelectQuery(); - if ( isUnequivocallySelect == TRUE ) { - throw new IllegalMutationQueryException( - "Expecting named native query (" + queryName + ") to be a mutation query, but found `" - + memento.getSqlString() + "`" - ); - } - if ( isEmpty( query.getComment() ) ) { - query.setComment( "dynamic native-SQL query" ); - } - applyQuerySettingsAndHints( query ); - return query; - } - - // Copy and paste from ORM: change the visibility instead - private SqmQueryImplementor createSqmQueryImplementor(String queryName, NamedSqmQueryMemento memento) { - final SqmQueryImplementor query = memento.toQuery( this ); - final SqmStatement sqmStatement = query.getSqmStatement(); - if ( !( sqmStatement instanceof SqmDmlStatement ) ) { - throw new IllegalMutationQueryException( - "Expecting a named mutation query (" + queryName + "), but found a select statement" - ); - } - if ( memento.getLockOptions() != null && ! memento.getLockOptions().isEmpty() ) { - throw new IllegalNamedQueryOptionsException( - "Named mutation query `" + queryName + "` specified lock-options" - ); - } - if ( isEmpty( query.getComment() ) ) { - query.setComment( "dynamic HQL query" ); - } - applyQuerySettingsAndHints( query ); - return query; - } - @Override public ReactiveSelectionQuery createNamedReactiveSelectionQuery(String queryName, Class expectedResultType) { return (ReactiveSelectionQuery) createNamedSelectionQuery( queryName , expectedResultType ); @@ -1107,16 +1000,6 @@ private void addAffectedEntities(AffectedEntities affectedEntities, NativeQueryI } } - //TODO: deleteme, call superclass method - private NamedResultSetMappingMemento getResultSetMappingMemento(String resultSetMappingName) { - final NamedResultSetMappingMemento resultSetMappingMemento = getFactory() - .getQueryEngine().getNamedObjectRepository().getResultSetMappingMemento( resultSetMappingName ); - if ( resultSetMappingMemento == null ) { - throw new HibernateException( "Could not resolve specified result-set mapping name: " + resultSetMappingName ); - } - return resultSetMappingMemento; - } - @Override public void close() { throw LOG.nonReactiveMethodCall( "close(CompletableFuture closing)" ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/ReactiveStandardMutationExecutorService.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/ReactiveStandardMutationExecutorService.java index 3355febe5..54dc193a2 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/ReactiveStandardMutationExecutorService.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/exec/internal/ReactiveStandardMutationExecutorService.java @@ -14,17 +14,15 @@ import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.persister.entity.mutation.EntityMutationTarget; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorPostInsert; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorPostInsertSingleTable; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorSingleBatched; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorSingleNonBatched; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorSingleSelfExecuting; import org.hibernate.reactive.engine.jdbc.mutation.internal.ReactiveMutationExecutorStandard; +import org.hibernate.sql.model.EntityMutationOperationGroup; import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationOperationGroup; -import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.PreparableMutationOperation; import org.hibernate.sql.model.SelfExecutingUpdateOperation; @@ -60,18 +58,16 @@ public MutationExecutor createExecutor( final int numberOfOperations = operationGroup.getNumberOfOperations(); final MutationType mutationType = operationGroup.getMutationType(); - final MutationTarget mutationTarget = operationGroup.getMutationTarget(); + final EntityMutationOperationGroup entityMutationOperationGroup = operationGroup.asEntityMutationOperationGroup(); if ( mutationType == MutationType.INSERT - && mutationTarget instanceof EntityMutationTarget - && ( (EntityMutationTarget) mutationTarget ).getIdentityInsertDelegate() != null ) { - assert mutationTarget instanceof EntityMappingType; - + && entityMutationOperationGroup != null + && entityMutationOperationGroup.getMutationTarget().getIdentityInsertDelegate() != null ) { if ( numberOfOperations > 1 ) { - return new ReactiveMutationExecutorPostInsert( operationGroup, session ); + return new ReactiveMutationExecutorPostInsert( entityMutationOperationGroup, session ); } - return new ReactiveMutationExecutorPostInsertSingleTable( operationGroup, session ); + return new ReactiveMutationExecutorPostInsertSingleTable( entityMutationOperationGroup, session ); } if ( numberOfOperations == 1 ) { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveDeferredResultSetAccess.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveDeferredResultSetAccess.java index 88fd2346e..c116abb10 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveDeferredResultSetAccess.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveDeferredResultSetAccess.java @@ -24,6 +24,7 @@ import org.hibernate.reactive.pool.ReactiveConnection; import org.hibernate.reactive.pool.impl.Parameters; import org.hibernate.reactive.session.ReactiveConnectionSupplier; +import org.hibernate.resource.jdbc.spi.JdbcSessionContext; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect; @@ -73,8 +74,7 @@ public ResultSet getResultSet() { @Override public CompletionStage getReactiveResultSet() { if ( resultSetStage == null ) { - resultSetStage = executeQuery() - .thenApply( this::saveResultSet ); + resultSetStage = executeQuery().thenApply( this::saveResultSet ); } return resultSetStage; } @@ -140,6 +140,10 @@ private static int columnCount(ResultSet resultSet) { } } + private JdbcSessionContext context() { + return executionContext.getSession().getJdbcCoordinator().getJdbcSessionOwner().getJdbcSessionContext(); + } + private CompletionStage executeQuery() { final LogicalConnectionImplementor logicalConnection = getPersistenceContext().getJdbcCoordinator().getLogicalConnection(); return completedFuture( logicalConnection ) @@ -162,7 +166,7 @@ private CompletionStage executeQuery() { .whenComplete( (resultSet, throwable) -> { // FIXME: I don't know if this event makes sense for Vert.x eventListenerManager.jdbcExecuteStatementEnd(); - sqlStatementLogger.logSlowQuery( getFinalSql(), executeStartNanos ); + sqlStatementLogger.logSlowQuery( getFinalSql(), executeStartNanos, context() ); } ) .thenCompose( this::reactiveSkipRows ) .handle( this::convertException ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java index b1b6842ad..105fdbb1f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java @@ -102,6 +102,11 @@ public Initializer resolveInitializer( public SqlAstCreationContext getSqlAstCreationContext() { return sessionFactory; } + + @Override + public ExecutionContext getExecutionContext() { + return executionContext; + } }; } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveArrayJdbcTypeConstructor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveArrayJdbcTypeConstructor.java new file mode 100644 index 000000000..da5dc2b21 --- /dev/null +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/type/descriptor/jdbc/ReactiveArrayJdbcTypeConstructor.java @@ -0,0 +1,42 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.type.descriptor.jdbc; + +import java.sql.Types; + +import org.hibernate.dialect.Dialect; +import org.hibernate.reactive.type.descriptor.jdbc.ReactiveArrayJdbcType; +import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation; +import org.hibernate.type.BasicType; +import org.hibernate.type.spi.TypeConfiguration; + +/** + * Factory for {@link ReactiveArrayJdbcType}. + */ +public class ReactiveArrayJdbcTypeConstructor implements JdbcTypeConstructor { + public static final ReactiveArrayJdbcTypeConstructor INSTANCE = new ReactiveArrayJdbcTypeConstructor(); + + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + BasicType elementType, + ColumnTypeInformation columnTypeInformation) { + return resolveType( typeConfiguration, dialect, elementType.getJdbcType(), columnTypeInformation ); + } + + public JdbcType resolveType( + TypeConfiguration typeConfiguration, + Dialect dialect, + JdbcType elementType, + ColumnTypeInformation columnTypeInformation) { + return new ReactiveArrayJdbcType( elementType ); + } + + @Override + public int getDefaultSqlTypeCode() { + return Types.ARRAY; + } +} diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JoinColumnsTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JoinColumnsTest.java index 6f642ed11..0b6a4e320 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JoinColumnsTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JoinColumnsTest.java @@ -10,14 +10,12 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.CompletionException; import org.hibernate.TransientPropertyValueException; import org.hibernate.reactive.BaseReactiveTest; import org.junit.jupiter.api.Test; -import io.smallrye.mutiny.Uni; import io.vertx.junit5.Timeout; import io.vertx.junit5.VertxTestContext; import jakarta.persistence.Column; @@ -33,8 +31,9 @@ import jakarta.persistence.Table; import static java.util.concurrent.TimeUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.reactive.testing.ReactiveAssertions.assertThrown; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; @Timeout(value = 10, timeUnit = MINUTES) @@ -171,19 +170,13 @@ public void testTransientReferenceExceptionWithStages(VertxTestContext context) final SampleJoinEntity sampleJoinEntity = new SampleJoinEntity(); sampleJoinEntity.name = "Joined entity name"; - test( context, getSessionFactory() + test( context, assertThrown( IllegalStateException.class, getSessionFactory() .withTransaction( (session, tx) -> { - sampleJoinEntity.sampleEntity = sampleEntity; - sampleEntity.sampleJoinEntities.add( sampleJoinEntity ); - return session.persist( sampleJoinEntity ); - } ) - .handle( (session, throwable) -> { - assertNotNull( throwable ); - assertEquals( CompletionException.class, throwable.getClass() ); - assertEquals( IllegalStateException.class, throwable.getCause().getClass() ); - assertEquals( TransientPropertyValueException.class, throwable.getCause().getCause().getClass() ); - return null; - } ) + sampleJoinEntity.sampleEntity = sampleEntity; + sampleEntity.sampleJoinEntities.add( sampleJoinEntity ); + return session.persist( sampleJoinEntity ); + } ) ) + .thenAccept( t -> assertThat( t ).hasCauseInstanceOf( TransientPropertyValueException.class ) ) ); } @@ -197,19 +190,13 @@ public void testTransientReferenceExceptionWithMutiny(VertxTestContext context) final SampleJoinEntity sampleJoinEntity = new SampleJoinEntity(); sampleJoinEntity.name = "Joined entity name"; - test( context, getMutinySessionFactory() - .withTransaction( (session, tx) -> { + test( context, assertThrown( IllegalStateException.class, getMutinySessionFactory() + .withTransaction( session -> { sampleJoinEntity.sampleEntity = sampleEntity; sampleEntity.sampleJoinEntities.add( sampleJoinEntity ); return session.persist( sampleJoinEntity ); - } ) - .onItem().invoke( v -> context.failNow( "Expected exception not thrown" ) ) - .onFailure().recoverWithUni( throwable -> { - assertNotNull( throwable ); - assertEquals( IllegalStateException.class, throwable.getClass() ); - assertEquals( TransientPropertyValueException.class, throwable.getCause().getClass() ); - return Uni.createFrom().nullItem(); - } ) + } ) ) + .invoke( t -> assertThat( t ).hasCauseInstanceOf( TransientPropertyValueException.class ) ) ); } From 5dec97c3ef2dc48bf2a11a59490cdbcca4517f62 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 25 Aug 2023 08:56:58 +0200 Subject: [PATCH 05/14] Fix latest compilation error --- .../ReactiveEntityInsertActionHolder.java | 2 +- .../internal/ReactiveMutationExecutor.java | 5 ++-- .../ReactiveMutationExecutorPostInsert.java | 29 ++++++++++--------- ...MutationExecutorPostInsertSingleTable.java | 23 +-------------- ...ReactiveMutationExecutorSingleBatched.java | 9 +++--- .../ReactiveMutationExecutorStandard.java | 3 +- ...ReactiveAbstractCollectionBatchLoader.java | 3 +- ...activeCollectionBatchLoaderArrayParam.java | 5 ++-- ...ctiveCollectionBatchLoaderInPredicate.java | 11 ++++--- .../ReactiveEntityBatchLoaderArrayParam.java | 5 ++-- .../ReactiveEntityBatchLoaderInPredicate.java | 9 +++--- ...ReactiveMultiIdEntityLoaderArrayParam.java | 4 +-- .../ReactiveBasicCollectionPersister.java | 9 +++--- .../impl/ReactiveOneToManyPersister.java | 11 ++++--- ...ReactiveDeleteRowsCoordinatorStandard.java | 3 +- ...ReactiveInsertRowsCoordinatorStandard.java | 3 +- .../ReactiveRemoveCoordinatorStandard.java | 6 ++-- .../ReactiveAbstractEntityInitializer.java | 6 ++-- .../ReactiveEntitySelectFetchInitializer.java | 12 ++++---- .../internal/ReactiveResultsHelper.java | 2 +- 20 files changed, 63 insertions(+), 97 deletions(-) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityInsertActionHolder.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityInsertActionHolder.java index 9cfff7f3b..79f685e78 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityInsertActionHolder.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/impl/ReactiveEntityInsertActionHolder.java @@ -28,7 +28,7 @@ public ReactiveEntityInsertActionHolder(ReactiveEntityInsertAction delegate) { } @Override - public Serializable[] getPropertySpaces() { + public String[] getPropertySpaces() { return delegate.getPropertySpaces(); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/env/internal/ReactiveMutationExecutor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/env/internal/ReactiveMutationExecutor.java index 3027958f9..6b839dc97 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/env/internal/ReactiveMutationExecutor.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/env/internal/ReactiveMutationExecutor.java @@ -27,7 +27,6 @@ import static org.hibernate.reactive.engine.jdbc.ResultsCheckerUtil.checkResults; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; /** * @see org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor @@ -95,7 +94,7 @@ default CompletionStage performReactiveNonBatchedMutation( final TableMapping tableDetails = statementDetails.getMutatingTableDetails(); if ( inclusionChecker != null && !inclusionChecker.include( tableDetails ) ) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Skipping execution of secondary insert : %s", tableDetails.getTableName() ); } return voidFuture(); @@ -116,7 +115,7 @@ default CompletionStage performReactiveNonBatchedMutation( // the optional table did not have a row return voidFuture(); } - checkResults( session, statementDetails, resultChecker, affectedRowCount, -1); + checkResults( session, statementDetails, resultChecker, affectedRowCount, -1 ); return voidFuture(); } ) .whenComplete( (o, throwable) -> { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java index 9a382c6cd..e5e331f08 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsert.java @@ -5,12 +5,9 @@ */ package org.hibernate.reactive.engine.jdbc.mutation.internal; -import static org.hibernate.reactive.engine.jdbc.ResultsCheckerUtil.checkResults; -import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicReference; + import org.hibernate.engine.jdbc.mutation.OperationResultChecker; import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.engine.jdbc.mutation.TableInclusionChecker; @@ -27,6 +24,10 @@ import org.hibernate.sql.model.EntityMutationOperationGroup; import org.hibernate.sql.model.ValuesAnalysis; +import static org.hibernate.reactive.engine.jdbc.ResultsCheckerUtil.checkResults; +import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture; +import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; + public class ReactiveMutationExecutorPostInsert extends MutationExecutorPostInsert implements ReactiveMutationExecutor { public ReactiveMutationExecutorPostInsert( @@ -48,20 +49,20 @@ public CompletionStage executeReactive(Object modelReference, ValuesAnal session ) .thenApply( this::logId ) - .thenCompose(id -> { - if (secondaryTablesStatementGroup == null) { - return completedFuture(id); + .thenCompose( id -> { + if ( secondaryTablesStatementGroup == null ) { + return completedFuture( id ); } - AtomicReference> res = new AtomicReference<>(completedFuture(id)); - secondaryTablesStatementGroup.forEachStatement((tableName, statementDetails) -> { - res.set(res.get().thenCompose(i -> reactiveExecuteWithId(i, tableName, statementDetails, inclusionChecker, resultChecker, session))); - }); + AtomicReference> res = new AtomicReference<>( completedFuture( id ) ); + secondaryTablesStatementGroup.forEachStatement( (tableName, statementDetails) -> { + res.set( res.get().thenCompose( i -> reactiveExecuteWithId( i, tableName, statementDetails, inclusionChecker, resultChecker, session ) ) ); + } ); return res.get(); - }); + } ); } private Object logId(Object identifier) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER .tracef( "Post-insert generated value : `%s` (%s)", identifier, mutationTarget.getNavigableRole().getFullPath() ); } @@ -84,7 +85,7 @@ private CompletionStage reactiveExecuteWithId( assert !tableDetails.isIdentifierTable(); if ( inclusionChecker != null && !inclusionChecker.include( tableDetails ) ) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Skipping execution of secondary insert : %s", tableDetails.getTableName() diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java index c469ac6d5..c3a72200b 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorPostInsertSingleTable.java @@ -5,7 +5,6 @@ */ package org.hibernate.reactive.engine.jdbc.mutation.internal; -import java.util.List; import java.util.concurrent.CompletionStage; import org.hibernate.engine.jdbc.mutation.OperationResultChecker; @@ -13,22 +12,15 @@ import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails; import org.hibernate.engine.jdbc.mutation.internal.MutationExecutorPostInsertSingleTable; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.jdbc.Expectation; import org.hibernate.persister.entity.mutation.EntityMutationTarget; import org.hibernate.reactive.engine.jdbc.env.internal.ReactiveMutationExecutor; import org.hibernate.reactive.id.insert.ReactiveInsertGeneratedIdentifierDelegate; -import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.model.EntityMutationOperationGroup; -import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.PreparableMutationOperation; -import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.ValuesAnalysis; -import org.hibernate.sql.model.jdbc.JdbcInsertMutation; import static org.hibernate.engine.jdbc.mutation.internal.ModelMutationHelper.identityPreparation; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; - public class ReactiveMutationExecutorPostInsertSingleTable extends MutationExecutorPostInsertSingleTable implements ReactiveMutationExecutor { @@ -44,19 +36,6 @@ public ReactiveMutationExecutorPostInsertSingleTable(EntityMutationOperationGrou this.identityInsertStatementDetails = identityPreparation( operation, session ); } - private static class ReactiveIdentityInsertMutation extends JdbcInsertMutation { - - public ReactiveIdentityInsertMutation( - TableMapping tableDetails, - MutationTarget mutationTarget, - String sql, - boolean callable, - Expectation expectation, - List parameterBinders) { - super( tableDetails, mutationTarget, sql, callable, expectation, parameterBinders ); - } - } - @Override public CompletionStage executeReactive( Object modelReference, @@ -75,7 +54,7 @@ public CompletionStage executeReactive( } private Object logId(Object identifier) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER .tracef( "Post-insert generated value : `%s` (%s)", identifier, mutationTarget.getNavigableRole().getFullPath() ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorSingleBatched.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorSingleBatched.java index c7dce5ad4..13fdcb832 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorSingleBatched.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorSingleBatched.java @@ -5,10 +5,8 @@ */ package org.hibernate.reactive.engine.jdbc.mutation.internal; -import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; import java.util.concurrent.CompletionStage; + import org.hibernate.engine.jdbc.batch.spi.BatchKey; import org.hibernate.engine.jdbc.mutation.JdbcValueBindings; import org.hibernate.engine.jdbc.mutation.OperationResultChecker; @@ -26,6 +24,9 @@ import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.ValuesAnalysis; +import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; +import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; + public class ReactiveMutationExecutorSingleBatched extends MutationExecutorSingleBatched implements ReactiveMutationExecutor { @@ -53,7 +54,7 @@ public CompletionStage performReactiveBatchedOperations( final TableMapping tableDetails = statementDetails.getMutatingTableDetails(); if ( inclusionChecker != null && !inclusionChecker.include( tableDetails ) ) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Skipping execution of secondary insert : %s", tableDetails.getTableName() ); } return voidFuture(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorStandard.java index e3d75a005..3c274c214 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/engine/jdbc/mutation/internal/ReactiveMutationExecutorStandard.java @@ -29,7 +29,6 @@ import static org.hibernate.reactive.util.impl.CompletionStages.failedFuture; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; /** * @see org.hibernate.engine.jdbc.mutation.internal.MutationExecutorStandard @@ -145,7 +144,7 @@ public CompletionStage performReactiveNonBatchedMutation( final TableMapping tableDetails = statementDetails.getMutatingTableDetails(); if ( inclusionChecker != null && !inclusionChecker.include( tableDetails ) ) { - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER .tracef( "Skipping execution of secondary insert : %s", tableDetails.getTableName() ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractCollectionBatchLoader.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractCollectionBatchLoader.java index fc7cdb316..2dfd55dc6 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractCollectionBatchLoader.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveAbstractCollectionBatchLoader.java @@ -17,7 +17,6 @@ import org.hibernate.reactive.loader.ast.spi.ReactiveCollectionBatchLoader; import org.hibernate.sql.results.internal.ResultsHelper; -import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** @@ -73,7 +72,7 @@ protected void finishInitializingKey( return; } - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Finishing initializing batch-fetched collection : %s.%s", attributeMapping.getNavigableRole().getFullPath(), key ); } 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 4185d3646..efeafdd02 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 @@ -36,7 +36,6 @@ import org.hibernate.sql.results.internal.RowTransformerStandardImpl; import org.hibernate.type.BasicType; -import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** @@ -58,7 +57,7 @@ public ReactiveCollectionBatchLoaderArrayParam( SessionFactoryImplementor sessionFactory) { super( domainBatchSize, loadQueryInfluencers, attributeMapping, sessionFactory ); - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Using ARRAY batch fetching strategy for collection `%s` : %s", attributeMapping.getNavigableRole().getFullPath(), @@ -100,7 +99,7 @@ public ReactiveCollectionBatchLoaderArrayParam( @Override public CompletionStage> reactiveLoad(Object key, SharedSessionContractImplementor session) { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Batch loading entity `%s#%s`", getLoadable().getNavigableRole().getFullPath(), diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderInPredicate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderInPredicate.java index 92a995620..230ba5ef4 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderInPredicate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveCollectionBatchLoaderInPredicate.java @@ -26,7 +26,6 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParametersList; -import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** @@ -54,7 +53,7 @@ public ReactiveCollectionBatchLoaderInPredicate( .getDialect() .getBatchLoadSizingStrategy() .determineOptimalBatchLoadSize( keyColumnCount, domainBatchSize, false ); - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Using IN-predicate batch fetching strategy for collection `%s` : %s (%s)", attributeMapping.getNavigableRole().getFullPath(), @@ -90,7 +89,7 @@ private static void doNothing(Object key1, int relativePosition, int absolutePos @Override public CompletionStage> reactiveLoad(Object key, SharedSessionContractImplementor session) { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Loading collection `%s#%s` by batch-fetch", getLoadable().getNavigableRole().getFullPath(), @@ -139,7 +138,7 @@ private CompletionStage initializeKeys( T[] keysToInitialize, int nonNullKeysToInitializeCount, SharedSessionContractImplementor session) { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Collection keys to batch-fetch initialize (`%s#%s`) %s", getLoadable().getNavigableRole().getFullPath(), @@ -175,7 +174,7 @@ private CompletionStage initializeKeys( }, ReactiveCollectionBatchLoaderInPredicate::doNothing, startIndex -> { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Processing collection batch-fetch chunk (`%s#%s`) %s - %s", getLoadable().getNavigableRole().getFullPath(), @@ -186,7 +185,7 @@ private CompletionStage initializeKeys( } }, (startIndex, nonNullElementCount) -> { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Finishing collection batch-fetch chunk (`%s#%s`) %s - %s (%s)", getLoadable().getNavigableRole().getFullPath(), 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 b0b60b6eb..9ff3c2ba7 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 @@ -31,7 +31,6 @@ import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect; import org.hibernate.sql.exec.spi.JdbcParameterBindings; -import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** @@ -55,7 +54,7 @@ public ReactiveEntityBatchLoaderArrayParam( super( entityDescriptor, sessionFactory ); this.domainBatchSize = domainBatchSize; - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Batch fetching enabled for `%s` (entity) using ARRAY strategy : %s", entityDescriptor.getEntityName(), @@ -107,7 +106,7 @@ public final CompletionStage load( LockOptions lockOptions, Boolean readOnly, SharedSessionContractImplementor session) { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Batch fetching entity `%s#%s`", getLoadable().getEntityName(), pkValue ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java index 78403e41f..0cbfda1c3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/loader/ast/internal/ReactiveEntityBatchLoaderInPredicate.java @@ -29,7 +29,6 @@ import org.hibernate.sql.exec.spi.JdbcParametersList; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; -import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** @@ -58,7 +57,7 @@ public ReactiveEntityBatchLoaderInPredicate( this.domainBatchSize = domainBatchSize; this.sqlBatchSize = sqlBatchSize; - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Batch fetching `%s` entity using padded IN-list : %s (%s)", entityDescriptor.getEntityName(), @@ -111,12 +110,12 @@ public final CompletionStage load( LockOptions lockOptions, Boolean readOnly, SharedSessionContractImplementor session) { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Batch loading entity `%s#%s`", getLoadable().getEntityName(), pkValue ); } final Object[] idsToInitialize = resolveIdsToLoad( pkValue, session ); - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Ids to batch-fetch initialize (`%s#%s`) %s", getLoadable().getEntityName(), @@ -186,7 +185,7 @@ protected CompletionStage initializeEntities( } }, (startIndex) -> { - if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( "Processing entity batch-fetch chunk (`%s#%s`) %s - %s", getLoadable().getEntityName(), 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 967581dbb..fd7cb8794 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 @@ -89,7 +89,7 @@ protected CompletionStage> performOrderedMultiLoad( K[] ids, MultiIdLoadOptions loadOptions, EventSource session) { - if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_TRACE_ENABLED ) { + if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.tracef( "ReactiveMultiIdEntityLoaderArrayParam#performOrderedMultiLoad - %s", getLoadable().getEntityName() @@ -246,7 +246,7 @@ protected CompletionStage> performUnorderedMultiLoad( K[] ids, MultiIdLoadOptions loadOptions, EventSource session) { - if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_TRACE_ENABLED ) { + if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.tracef( "ReactiveMultiIdEntityLoaderArrayParam#performUnorderedMultiLoad - %s", getLoadable().getEntityName() diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java index 80e312327..d664a6398 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveBasicCollectionPersister.java @@ -38,7 +38,6 @@ import org.hibernate.reactive.util.impl.CompletionStages; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; /** * A reactive {@link BasicCollectionPersister} @@ -78,7 +77,7 @@ private ReactiveUpdateRowsCoordinator buildUpdateRowCoordinator() { && !isInverse(); if ( !performUpdates ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection row updates - %s", getRolePath() ); } return new ReactiveUpdateRowsCoordinatorNoOp( this ); @@ -89,7 +88,7 @@ private ReactiveUpdateRowsCoordinator buildUpdateRowCoordinator() { private ReactiveInsertRowsCoordinator buildInsertRowCoordinator() { if ( isInverse() || !isRowInsertEnabled() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection inserts - %s", getRolePath() ); } return new ReactiveInsertRowsCoordinatorNoOp( this ); @@ -100,7 +99,7 @@ private ReactiveInsertRowsCoordinator buildInsertRowCoordinator() { private ReactiveDeleteRowsCoordinator buildDeleteRowCoordinator() { if ( ! needsRemove() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection row deletions - %s", getRolePath() ); } return new ReactiveDeleteRowsCoordinatorNoOp( this ); @@ -116,7 +115,7 @@ private ReactiveDeleteRowsCoordinator buildDeleteRowCoordinator() { private ReactiveRemoveCoordinator buildDeleteAllCoordinator() { if ( ! needsRemove() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection removals - %s", getRolePath() ); } return new ReactiveRemoveCoordinatorNoOp( this ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java index 526acea85..6e4929f48 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/impl/ReactiveOneToManyPersister.java @@ -49,7 +49,6 @@ import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; import static org.hibernate.sql.model.MutationType.UPDATE; import static org.hibernate.sql.model.internal.MutationOperationGroupFactory.singleOperation; @@ -109,7 +108,7 @@ public ReactiveRemoveCoordinator getRemoveCoordinator() { private ReactiveInsertRowsCoordinator buildInsertCoordinator() { if ( isInverse() || !isRowInsertEnabled() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection (re)creation - %s", getRolePath() ); } return new ReactiveInsertRowsCoordinatorNoOp( this ); @@ -119,7 +118,7 @@ private ReactiveInsertRowsCoordinator buildInsertCoordinator() { private ReactiveUpdateRowsCoordinator buildUpdateCoordinator() { if ( !isRowDeleteEnabled() && !isRowInsertEnabled() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection row updates - %s", getRolePath() ); } return new ReactiveUpdateRowsCoordinatorNoOp( this ); @@ -129,7 +128,7 @@ private ReactiveUpdateRowsCoordinator buildUpdateCoordinator() { private ReactiveDeleteRowsCoordinator buildDeleteCoordinator() { if ( !needsRemove() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection row deletions - %s", getRolePath() ); } return new ReactiveDeleteRowsCoordinatorNoOp( this ); @@ -145,7 +144,7 @@ private ReactiveDeleteRowsCoordinator buildDeleteCoordinator() { private ReactiveRemoveCoordinator buildDeleteAllCoordinator() { if ( ! needsRemove() ) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER.debugf( "Skipping collection removals - %s", getRolePath() ); } return new ReactiveRemoveCoordinatorNoOp( this ); @@ -243,7 +242,7 @@ private BasicBatchKey getBasicBatchKey() { * @see OneToManyPersister#recreate(PersistentCollection, Object, SharedSessionContractImplementor) */ @Override - public CompletionStage reactiveRecreate(PersistentCollection collection, Object id, SharedSessionContractImplementor session) throws HibernateException { + public CompletionStage reactiveRecreate(PersistentCollection collection, Object id, SharedSessionContractImplementor session) throws HibernateException { return getInsertRowsCoordinator() .reactiveInsertRows( collection, id, collection::includeInRecreate, session ) .thenCompose( unused -> writeIndex( collection, collection.entries( this ), id, true, session ) ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java index 2c099df6b..9e1b4672f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveDeleteRowsCoordinatorStandard.java @@ -28,7 +28,6 @@ import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; public class ReactiveDeleteRowsCoordinatorStandard extends DeleteRowsCoordinatorStandard implements ReactiveDeleteRowsCoordinator { private final RowMutationOperations rowMutationOperations; @@ -53,7 +52,7 @@ public CompletionStage reactiveDeleteRows(PersistentCollection collecti operationGroup = createOperationGroup(); } - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER .debugf( "Deleting removed collection rows - %s : %s", getMutationTarget().getRolePath(), key ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java index 9c941be40..ea580fcfc 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveInsertRowsCoordinatorStandard.java @@ -30,7 +30,6 @@ import static org.hibernate.reactive.util.impl.CompletionStages.loop; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; /** * @see InsertRowsCoordinatorStandard @@ -71,7 +70,7 @@ public CompletionStage reactiveInsertRows(PersistentCollection collecti operationGroup = createOperationGroup(); } - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER .debugf( "Inserting collection rows - %s : %s", mutationTarget.getRolePath(), id ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java index a8d730f7e..ed5a0fb80 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/collection/mutation/ReactiveRemoveCoordinatorStandard.java @@ -28,8 +28,6 @@ import static org.hibernate.persister.collection.mutation.RowMutationOperations.DEFAULT_RESTRICTOR; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED; -import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER_TRACE_ENABLED; import static org.hibernate.sql.model.MutationType.DELETE; import static org.hibernate.sql.model.internal.MutationOperationGroupFactory.singleOperation; @@ -56,7 +54,7 @@ private BasicBatchKey getBatchKey() { @Override public CompletionStage reactiveDeleteAllRows(Object key, SharedSessionContractImplementor session) { - if ( MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isDebugEnabled() ) { MODEL_MUTATION_LOGGER .debugf( "Deleting collection - %s : %s", getMutationTarget().getRolePath(), key ); } @@ -98,7 +96,7 @@ private MutationOperationGroup buildOperationGroup() { assert getMutationTarget().getTargetPart() != null; assert getMutationTarget().getTargetPart().getKeyDescriptor() != null; - if ( MODEL_MUTATION_LOGGER_TRACE_ENABLED ) { + if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Starting RemoveCoordinator#buildOperationGroup - %s", getMutationTarget().getRolePath() ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/ReactiveAbstractEntityInitializer.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/ReactiveAbstractEntityInitializer.java index abbfa6e1f..389cee1f3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/ReactiveAbstractEntityInitializer.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/ReactiveAbstractEntityInitializer.java @@ -146,7 +146,7 @@ private Object resolveInstance( } else { // the entity is already being loaded elsewhere - if ( EntityLoadingLogging.DEBUG_ENABLED ) { + if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", getSimpleConcreteImplName(), @@ -189,7 +189,7 @@ private CompletionStage initializeEntityInstance(Object toInitialize, RowP final SharedSessionContractImplementor session = rowProcessingState.getSession(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - if ( EntityLoadingLogging.TRACE_ENABLED ) { + if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isTraceEnabled() ) { EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef( "(%s) Beginning Initializer#initializeInstance process for entity %s", getSimpleConcreteImplName(), @@ -249,7 +249,7 @@ private CompletionStage initializeEntityInstance(Object toInitialize, RowP registerNaturalIdResolution( persistenceContext, entityIdentifier ); takeSnapshot( rowProcessingState, session, persistenceContext, entityEntry ); getConcreteDescriptor().afterInitialize( toInitialize, session ); - if ( EntityLoadingLogging.DEBUG_ENABLED ) { + if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( "(%s) Done materializing entityInstance : %s", getSimpleConcreteImplName(), diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntitySelectFetchInitializer.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntitySelectFetchInitializer.java index 119351b9f..45af27613 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntitySelectFetchInitializer.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/graph/entity/internal/ReactiveEntitySelectFetchInitializer.java @@ -30,7 +30,6 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParentAccess; -import org.hibernate.sql.results.graph.entity.EntityLoadingLogging; import org.hibernate.sql.results.graph.entity.LoadingEntityEntry; import org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializer; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -41,7 +40,6 @@ import static org.hibernate.reactive.util.impl.CompletionStages.failedFuture; import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture; import static org.hibernate.reactive.util.impl.CompletionStages.whileLoop; -import static org.hibernate.sql.results.graph.entity.EntityLoadingLogging.DEBUG_ENABLED; import static org.hibernate.sql.results.graph.entity.EntityLoadingLogging.ENTITY_LOADING_LOGGER; /** @@ -113,7 +111,7 @@ public CompletionStage reactiveInitializeInstance(ReactiveRowProcessingSta return voidFuture(); } - if ( EntityLoadingLogging.TRACE_ENABLED ) { + if ( ENTITY_LOADING_LOGGER.isTraceEnabled() ) { ENTITY_LOADING_LOGGER.tracef( "(%s) Beginning Initializer#resolveInstance process for entity (%s) : %s", StringHelper.collapse( this.getClass().getName() ), @@ -145,7 +143,7 @@ public CompletionStage reactiveInitializeInstance(ReactiveRowProcessingSta .findLoadingEntityEntry( entityKey ); if ( existingLoadingEntry != null ) { - if ( DEBUG_ENABLED ) { + if ( ENTITY_LOADING_LOGGER.isDebugEnabled() ) { ENTITY_LOADING_LOGGER.debugf( "(%s) Found existing loading entry [%s] - using loading instance", CONCRETE_NAME, @@ -156,7 +154,7 @@ public CompletionStage reactiveInitializeInstance(ReactiveRowProcessingSta if ( existingLoadingEntry.getEntityInitializer() != this ) { // the entity is already being loaded elsewhere - if ( DEBUG_ENABLED ) { + if ( ENTITY_LOADING_LOGGER.isDebugEnabled() ) { ENTITY_LOADING_LOGGER.debugf( "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", CONCRETE_NAME, @@ -171,7 +169,7 @@ public CompletionStage reactiveInitializeInstance(ReactiveRowProcessingSta } } - if ( DEBUG_ENABLED ) { + if ( ENTITY_LOADING_LOGGER.isDebugEnabled() ) { ENTITY_LOADING_LOGGER.debugf( "(%s) Invoking session#internalLoad for entity (%s) : %s", CONCRETE_NAME, @@ -191,7 +189,7 @@ public CompletionStage reactiveInitializeInstance(ReactiveRowProcessingSta } } - if ( DEBUG_ENABLED ) { + if ( ENTITY_LOADING_LOGGER.isDebugEnabled() ) { ENTITY_LOADING_LOGGER.debugf( "(%s) Entity [%s] : %s has being loaded by session.internalLoad.", CONCRETE_NAME, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java index 105fdbb1f..95db00c8f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/sql/results/internal/ReactiveResultsHelper.java @@ -111,7 +111,7 @@ public ExecutionContext getExecutionContext() { } private static void logInitializers(Map initializerMap) { - if ( ! ResultsLogger.DEBUG_ENABLED ) { + if ( ! ResultsLogger.RESULTS_MESSAGE_LOGGER.isDebugEnabled() ) { return; } From ae7be49d48506683ae5b26ee8a453e8f9c316374 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 11 Jul 2023 10:12:33 +0200 Subject: [PATCH 06/14] two more fixes to Session API 1. fix the broken signature of createSelectionQuery() oops! 2. #1703 add enableFetchProfile() to Query --- .../org/hibernate/reactive/mutiny/Mutiny.java | 11 ++++- .../reactive/mutiny/impl/MutinyQueryImpl.java | 6 +++ .../mutiny/impl/MutinySelectionQueryImpl.java | 12 ++++-- .../mutiny/impl/MutinySessionImpl.java | 4 +- .../query/ReactiveSelectionQuery.java | 3 ++ .../spi/ReactiveAbstractSelectionQuery.java | 43 +++++++++++++++++-- .../sql/internal/ReactiveNativeQueryImpl.java | 5 +++ .../sqm/internal/ReactiveQuerySqmImpl.java | 12 +++--- .../ReactiveSqmSelectionQueryImpl.java | 5 +++ .../session/ReactiveQueryProducer.java | 2 - .../session/impl/ReactiveSessionImpl.java | 5 --- .../impl/ReactiveStatelessSessionImpl.java | 5 --- .../org/hibernate/reactive/stage/Stage.java | 8 +++- .../reactive/stage/impl/StageQueryImpl.java | 7 +++ .../stage/impl/StageSelectionQueryImpl.java | 6 +++ .../reactive/stage/impl/StageSessionImpl.java | 4 +- .../LazyManyToOneAssociationTest.java | 31 +++++++++++++ .../reactive/ReactiveSessionTest.java | 6 +-- 18 files changed, 142 insertions(+), 33 deletions(-) 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 b53fd2eae..ed4683897 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 @@ -347,6 +347,12 @@ default SelectionQuery setLockMode(String alias, LockModeType lockModeType) { */ SelectionQuery setPlan(EntityGraph entityGraph); + /** + * Enable a {@linkplain org.hibernate.annotations.FetchProfile fetch + * profile} which will be in effect during execution of this query. + */ + SelectionQuery enableFetchProfile(String profileName); + @Override SelectionQuery setParameter(int parameter, Object argument); @@ -456,6 +462,9 @@ default Query setLockMode(String alias, LockModeType lockModeType) { @Override Query setComment(String comment); + + @Override + Query enableFetchProfile(String profileName); } @@ -863,7 +872,7 @@ default Uni lock(Object entity, LockModeType lockModeType) { * * @see jakarta.persistence.EntityManager#createQuery(String, Class) */ - SelectionQuery createSelectionQuery(String queryString); + SelectionQuery createSelectionQuery(String queryString, Class resultType); /** * Create an instance of {@link MutationQuery} for the given HQL/JPQL diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java index c936ec005..a0d3494be 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java @@ -71,6 +71,12 @@ public Query setPlan(EntityGraph entityGraph) { return this; } + @Override + public Query enableFetchProfile(String profileName) { + delegate.enableFetchProfile( profileName ); + return this; + } + @Override public Uni getSingleResult() { return uni( delegate::getReactiveSingleResult ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java index 9d38a0a07..9275b3336 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java @@ -18,7 +18,7 @@ import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.reactive.mutiny.Mutiny.SelectionQuery; -import org.hibernate.reactive.query.ReactiveQuery; +import org.hibernate.reactive.query.ReactiveSelectionQuery; import java.util.List; import java.util.concurrent.CompletionStage; @@ -26,9 +26,9 @@ public class MutinySelectionQueryImpl implements SelectionQuery { private final MutinySessionFactoryImpl factory; - private final ReactiveQuery delegate; + private final ReactiveSelectionQuery delegate; - public MutinySelectionQueryImpl(ReactiveQuery delegate, MutinySessionFactoryImpl factory) { + public MutinySelectionQueryImpl(ReactiveSelectionQuery delegate, MutinySessionFactoryImpl factory) { this.delegate = delegate; this.factory = factory; } @@ -209,4 +209,10 @@ public SelectionQuery setComment(String comment) { delegate.setComment( comment ); return this; } + + @Override + public SelectionQuery enableFetchProfile(String profileName) { + delegate.enableFetchProfile( profileName ); + return this; + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java index 5a31741be..72fb82d3f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java @@ -116,8 +116,8 @@ public boolean contains(Object entity) { } @Override - public SelectionQuery createSelectionQuery(String queryString) { - return new MutinySelectionQueryImpl<>( delegate.createReactiveQuery( queryString ), factory ); + public SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return new MutinySelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString, resultType ), factory ); } @Override diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java index ac0388d97..bd090cfd9 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java @@ -115,12 +115,15 @@ default CompletionStage> getReactiveResultList() { ReactiveSelectionQuery setLockMode(String alias, LockMode lockMode); + @Deprecated ReactiveSelectionQuery setAliasSpecificLockMode(String alias, LockMode lockMode); ReactiveSelectionQuery setFollowOnLocking(boolean enable); void applyGraph(RootGraphImplementor graph, GraphSemantic semantic); + void enableFetchProfile(String profileName); + @Override ReactiveSelectionQuery setParameter(String name, Object value); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java index 6bf2f47a8..9054d60a6 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/spi/ReactiveAbstractSelectionQuery.java @@ -6,8 +6,7 @@ package org.hibernate.reactive.query.spi; import java.lang.invoke.MethodHandles; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; import java.util.function.Consumer; @@ -18,6 +17,7 @@ import org.hibernate.HibernateException; import org.hibernate.LockOptions; import org.hibernate.TypeMismatchException; +import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.query.IllegalQueryOperationException; import org.hibernate.query.hql.internal.QuerySplitter; @@ -37,6 +37,8 @@ import jakarta.persistence.NoResultException; +import static java.util.Collections.emptySet; + /** * Emulate {@link org.hibernate.query.spi.AbstractSelectionQuery}. *

@@ -63,6 +65,8 @@ public class ReactiveAbstractSelectionQuery { private final Supplier> getResultType; private final Supplier getQueryString; + private Set fetchProfiles; + private final Runnable beforeQuery; private final Consumer afterQuery; @@ -175,13 +179,40 @@ private LockOptions getLockOptions() { } public CompletionStage> reactiveList() { + final Set profiles = applyProfiles(); beforeQuery.run(); return doReactiveList() .handle( (list, error) -> { handleException( error ); return list; } ) - .whenComplete( (rs, throwable) -> afterQuery.accept( throwable == null ) ); + .whenComplete( (rs, throwable) -> { + afterQuery.accept( throwable == null ); + unapplyProfiles( profiles ); + } ); + } + + private void unapplyProfiles(Set profiles) { + for ( String profile : profiles) { + session.getLoadQueryInfluencers().disableFetchProfile( profile ); + } + } + + private Set applyProfiles() { + final LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers(); + if ( fetchProfiles != null ) { + final Set profiles = new HashSet<>( fetchProfiles.size() ); + for ( String profile : fetchProfiles ) { + if ( !loadQueryInfluencers.isFetchProfileEnabled( profile ) ) { + loadQueryInfluencers.enableFetchProfile( profile ); + profiles.add( profile ); + } + } + return profiles; + } + else { + return emptySet(); + } } private void handleException(Throwable e) { @@ -312,4 +343,10 @@ public Optional uniqueResultOptional() { throw LOG.nonReactiveMethodCall( "reactiveUniqueResultOptional" ); } + public void enableFetchProfile(String profileName) { + if ( fetchProfiles == null ) { + fetchProfiles = new HashSet<>(); + } + fetchProfiles.add( profileName ); + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java index 031d961f7..282312d55 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java @@ -741,4 +741,9 @@ public ReactiveNativeQueryImpl setProperties(Map bean) { public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { super.applyGraph( graph, semantic ); } + + @Override + public void enableFetchProfile(String profileName) { + throw new UnsupportedOperationException("A native SQL query cannot use fetch profiles"); + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java index 3165b886e..0edb66a11 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java @@ -7,12 +7,7 @@ import java.lang.invoke.MethodHandles; import java.time.Instant; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CompletionStage; import java.util.stream.Stream; @@ -831,4 +826,9 @@ public ReactiveQuerySqmImpl setFollowOnLocking(boolean enable) { public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { super.applyGraph( graph, semantic ); } + + @Override + public void enableFetchProfile(String profileName) { + selectionQueryDelegate.enableFetchProfile( profileName ); + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java index 685599037..a19c1cadf 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java @@ -588,4 +588,9 @@ public ReactiveSqmSelectionQueryImpl setProperties(Object bean) { public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { getQueryOptions().applyGraph( graph, semantic ); } + + @Override + public void enableFetchProfile(String profileName) { + selectionQueryDelegate.enableFetchProfile( profileName ); + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/ReactiveQueryProducer.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/ReactiveQueryProducer.java index 3bb610752..e67605c81 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/ReactiveQueryProducer.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/session/ReactiveQueryProducer.java @@ -69,8 +69,6 @@ public interface ReactiveQueryProducer extends ReactiveConnectionSupplier { ReactiveNativeQuery createReactiveNativeQuery(String sqlString, String resultSetMappingName, Class resultClass); - ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString); - ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString, Class resultType); ReactiveSelectionQuery createReactiveSelectionQuery(CriteriaQuery criteria); 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 bafbcad61..04b83a155 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 @@ -467,11 +467,6 @@ public ReactiveNativeQuery createReactiveNativeQuery(String sqlString, St return query; } - @Override - public ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString) { - return interpretAndCreateSelectionQuery( hqlString, null ); - } - @Override public ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString, Class resultType) { return interpretAndCreateSelectionQuery( hqlString, resultType ); 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 afd7b2e5a..d7fa353b5 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 @@ -791,11 +791,6 @@ public ReactiveNativeQuery createReactiveNativeQuery( return query; } - @Override - public ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString) { - return interpretAndCreateSelectionQuery( hqlString, null ); - } - @Override public ReactiveSelectionQuery createReactiveSelectionQuery(String hqlString, Class resultType) { return interpretAndCreateSelectionQuery( hqlString, resultType ); 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 80a522112..1ed8af806 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 @@ -349,6 +349,12 @@ default SelectionQuery setLockMode(String alias, LockModeType lockModeType) { */ SelectionQuery setPlan(EntityGraph entityGraph); + /** + * Enable a {@linkplain org.hibernate.annotations.FetchProfile fetch + * profile} which will be in effect during execution of this query. + */ + SelectionQuery enableFetchProfile(String profileName); + @Override SelectionQuery setParameter(int parameter, Object argument); @@ -903,7 +909,7 @@ default CompletionStage lock(Object entity, LockModeType lockModeType) { * * @see jakarta.persistence.EntityManager#createQuery(String, Class) */ - SelectionQuery createSelectionQuery(String queryString); + SelectionQuery createSelectionQuery(String queryString, Class resultType); /** * Create an instance of {@link MutationQuery} for the given HQL/JPQL diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java index 9bf79b4e8..b072ee05a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java @@ -17,6 +17,7 @@ import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.reactive.query.ReactiveQuery; +import org.hibernate.reactive.stage.Stage; import org.hibernate.reactive.stage.Stage.Query; import java.util.List; @@ -62,6 +63,12 @@ public Query setPlan(EntityGraph entityGraph) { return this; } + @Override + public Stage.SelectionQuery enableFetchProfile(String profileName) { + delegate.enableFetchProfile( profileName ); + return this; + } + @Override public CompletionStage getSingleResult() { return delegate.getReactiveSingleResult(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java index fe953ee90..62a3944ea 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java @@ -62,6 +62,12 @@ public SelectionQuery setPlan(EntityGraph entityGraph) { return this; } + @Override + public SelectionQuery enableFetchProfile(String profileName) { + delegate.enableFetchProfile( profileName ); + return this; + } + @Override public CompletionStage getSingleResult() { return delegate.getReactiveSingleResult(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java index c62327e82..6e6ff1e0b 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java @@ -108,8 +108,8 @@ public boolean contains(Object entity) { } @Override - public SelectionQuery createSelectionQuery(String queryString) { - return new StageSelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString ) ); + public SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return new StageSelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString, resultType ) ); } @Override diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/LazyManyToOneAssociationTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/LazyManyToOneAssociationTest.java index be28ebef3..13746e7e0 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/LazyManyToOneAssociationTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/LazyManyToOneAssociationTest.java @@ -71,6 +71,37 @@ public void fetchProfileWithOneAuthor(VertxTestContext context) { ); } + @Test + public void fetchProfileOnQuery(VertxTestContext context) { + final Book book = new Book( 6, "The Boy, The Mole, The Fox and The Horse" ); + final Author author = new Author( 5, "Charlie Mackesy", book ); + + test( + context, + openSession() + .thenCompose( s -> s.persist( book ) + .thenCompose( v -> s.persist( author ) ) + .thenCompose( v -> s.flush() ) ) + .thenCompose( v -> openSession() + .thenCompose( s -> s.createSelectionQuery( "from Author where id = ?1", Author.class ) + .enableFetchProfile( "withBook" ) + .setParameter(1, author.getId() ) + .getSingleResultOrNull() ) ) + .thenAccept( optionalAuthor -> { + assertNotNull( optionalAuthor ); + assertEquals( author, optionalAuthor ); + assertTrue( isInitialized( optionalAuthor.getBook() ) ); + assertEquals( book, optionalAuthor.getBook() ); + } ) + .thenCompose( v -> openSession() + .thenCompose( s -> s.find( Book.class, book.getId() ) ) ) + .thenAccept( optionalBook -> { + assertNotNull( optionalBook ); + assertEquals( book, optionalBook ); + } ) + ); + } + @Test public void namedEntityGraphWithOneAuthor(VertxTestContext context) { final Book book = new Book( 6, "The Boy, The Mole, The Fox and The Horse" ); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java index 3f1012b2b..b47eed56e 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/ReactiveSessionTest.java @@ -886,7 +886,7 @@ public void testCreateSelectionQueryMultiple(VertxTestContext context) { ) .thenCompose( v -> openSession() ) .thenCompose( session -> session - .createSelectionQuery( "from GuineaPig" ) + .createSelectionQuery( "from GuineaPig", GuineaPig.class ) .getResultList() .thenAccept( resultList -> assertThat( resultList ).containsExactlyInAnyOrder( aloiPig, bloiPig ) ) ) ) ); @@ -903,7 +903,7 @@ public void testCreateSelectionQuerySingle(VertxTestContext context) { .getSingleResult() .thenAccept( actualPig -> assertThatPigsAreEqual( expectedPig, actualPig ) ) ) .thenCompose( v -> openSession() ) - .thenCompose( session -> session.createSelectionQuery( "from GuineaPig" ) + .thenCompose( session -> session.createSelectionQuery( "from GuineaPig", GuineaPig.class ) .getSingleResult() .thenAccept( actualPig -> assertThatPigsAreEqual( expectedPig, (GuineaPig) actualPig ) ) ) ) @@ -917,7 +917,7 @@ public void testCreateSelectionQueryNull(VertxTestContext context) { .getSingleResultOrNull() .thenAccept( Assertions::assertNull ) ) .thenCompose( v -> openSession() ) - .thenCompose( session -> session.createSelectionQuery( "from GuineaPig" ) + .thenCompose( session -> session.createSelectionQuery( "from GuineaPig", GuineaPig.class ) .getSingleResultOrNull() .thenAccept( Assertions::assertNull ) ) ); From 613d1fd3e556bffd70380af710422cdc018e4a4f Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 11 Jul 2023 10:38:45 +0200 Subject: [PATCH 07/14] deprecate createQuery(String) due to confusing semantics in Hibernate 6 also add missing createSelectionQuery()/createMutationQuery() to StatelessSession --- .../org/hibernate/reactive/mutiny/Mutiny.java | 32 +++++++++++++++++++ .../mutiny/impl/MutinyMutationQueryImpl.java | 6 ++-- .../mutiny/impl/MutinySessionImpl.java | 7 ++-- .../impl/MutinyStatelessSessionImpl.java | 12 ++++++- .../org/hibernate/reactive/stage/Stage.java | 32 +++++++++++++++++++ .../reactive/stage/impl/StageSessionImpl.java | 2 +- .../stage/impl/StageStatelessSessionImpl.java | 12 ++++++- 7 files changed, 93 insertions(+), 10 deletions(-) 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 ed4683897..954c8fbb1 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 @@ -896,8 +896,12 @@ default Uni lock(Object entity, LockModeType lockModeType) { * * @return The {@link Query} instance for manipulation and execution * + * @deprecated See explanation in + * {@link org.hibernate.query.QueryProducer#createSelectionQuery(String)} + * * @see jakarta.persistence.EntityManager#createQuery(String) */ + @Deprecated Query createQuery(String queryString); /** @@ -1461,8 +1465,12 @@ default Uni get(Class entityClass, Object id, LockModeType lockModeTyp * * @return The {@link Query} instance for manipulation and execution * + * @deprecated See explanation in + * {@link org.hibernate.query.QueryProducer#createSelectionQuery(String)} + * * @see Session#createQuery(String) */ + @Deprecated Query createQuery(String queryString); /** @@ -1478,6 +1486,30 @@ default Uni get(Class entityClass, Object id, LockModeType lockModeTyp */ SelectionQuery createQuery(String queryString, Class resultType); + /** + * Create an instance of {@link SelectionQuery} for the given HQL/JPQL + * query string. + * + * @param queryString The HQL/JPQL query + * + * @return The {@link SelectionQuery} instance for manipulation and execution + * + * @see jakarta.persistence.EntityManager#createQuery(String, Class) + */ + SelectionQuery createSelectionQuery(String queryString, Class resultType); + + /** + * Create an instance of {@link MutationQuery} for the given HQL/JPQL + * update or delete statement. + * + * @param queryString The HQL/JPQL query, update or delete statement + * + * @return The {@link MutationQuery} instance for manipulation and execution + * + * @see jakarta.persistence.EntityManager#createQuery(String) + */ + MutationQuery createMutationQuery(String queryString); + /** * Create an instance of {@link Query} for the named query. * diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyMutationQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyMutationQueryImpl.java index 1385e5eb6..44b50f986 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyMutationQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyMutationQueryImpl.java @@ -8,7 +8,7 @@ import io.smallrye.mutiny.Uni; import jakarta.persistence.Parameter; import org.hibernate.reactive.mutiny.Mutiny.MutationQuery; -import org.hibernate.reactive.query.ReactiveQuery; +import org.hibernate.reactive.query.ReactiveMutationQuery; import java.util.concurrent.CompletionStage; import java.util.function.Supplier; @@ -16,9 +16,9 @@ public class MutinyMutationQueryImpl implements MutationQuery { private final MutinySessionFactoryImpl factory; - private final ReactiveQuery delegate; + private final ReactiveMutationQuery delegate; - public MutinyMutationQueryImpl(ReactiveQuery delegate, MutinySessionFactoryImpl factory) { + public MutinyMutationQueryImpl(ReactiveMutationQuery delegate, MutinySessionFactoryImpl factory) { this.delegate = delegate; this.factory = factory; } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java index 72fb82d3f..7cc230ec5 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySessionImpl.java @@ -33,7 +33,6 @@ import org.hibernate.reactive.mutiny.Mutiny.Query; import org.hibernate.reactive.mutiny.Mutiny.SelectionQuery; import org.hibernate.reactive.pool.ReactiveConnection; -import org.hibernate.reactive.query.sqm.internal.ReactiveQuerySqmImpl; import org.hibernate.reactive.session.ReactiveConnectionSupplier; import org.hibernate.reactive.session.ReactiveQueryProducer; import org.hibernate.reactive.session.ReactiveSession; @@ -125,7 +124,7 @@ public MutationQuery createMutationQuery(String queryString) { return new MutinyMutationQueryImpl<>( delegate.createReactiveQuery( queryString ), factory ); } - @Override + @Override @Deprecated public Query createQuery(String queryString) { return new MutinyQueryImpl<>( delegate.createReactiveQuery( queryString ), factory ); } @@ -143,7 +142,7 @@ public SelectionQuery createQuery(CriteriaQuery criteriaQuery) { @Override public MutationQuery createQuery(CriteriaUpdate criteriaUpdate) { return new MutinyMutationQueryImpl<>( - (ReactiveQuerySqmImpl) delegate.createReactiveMutationQuery( criteriaUpdate ), + delegate.createReactiveMutationQuery( criteriaUpdate ), factory ); } @@ -151,7 +150,7 @@ public MutationQuery createQuery(CriteriaUpdate criteriaUpdate) { @Override public MutationQuery createQuery(CriteriaDelete criteriaDelete) { return new MutinyMutationQueryImpl<>( - (ReactiveQuerySqmImpl) delegate.createReactiveMutationQuery( criteriaDelete ), + delegate.createReactiveMutationQuery( criteriaDelete ), factory ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyStatelessSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyStatelessSessionImpl.java index 7764075e3..ceaf5730d 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyStatelessSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyStatelessSessionImpl.java @@ -68,11 +68,21 @@ public Query createQuery(String queryString) { return new MutinyQueryImpl<>( delegate.createReactiveQuery( queryString ), factory ); } - @Override + @Override @Deprecated public SelectionQuery createQuery(String queryString, Class resultType) { return new MutinySelectionQueryImpl<>( delegate.createReactiveQuery( queryString, resultType ), factory ); } + @Override + public SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return new MutinySelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString, resultType), factory ); + } + + @Override + public Mutiny.MutationQuery createMutationQuery(String queryString) { + return new MutinyMutationQueryImpl<>( delegate.createReactiveMutationQuery( queryString), factory ); + } + @Override public Query createNamedQuery(String queryName) { return new MutinyQueryImpl<>( delegate.createReactiveNamedQuery( queryName, null ), factory ); 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 1ed8af806..b14297b8a 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 @@ -933,8 +933,12 @@ default CompletionStage lock(Object entity, LockModeType lockModeType) { * * @return The {@link Query} instance for manipulation and execution * + * @deprecated See explanation in + * {@link org.hibernate.query.QueryProducer#createSelectionQuery(String)} + * * @see jakarta.persistence.EntityManager#createQuery(String) */ + @Deprecated Query createQuery(String queryString); /** @@ -1496,8 +1500,12 @@ default CompletionStage get(Class entityClass, Object id, LockModeType * * @return The {@link Query} instance for manipulation and execution * + * @deprecated See explanation in + * {@link org.hibernate.query.QueryProducer#createSelectionQuery(String)} + * * @see org.hibernate.Session#createQuery(String) */ + @Deprecated Query createQuery(String queryString); /** @@ -1513,6 +1521,30 @@ default CompletionStage get(Class entityClass, Object id, LockModeType */ SelectionQuery createQuery(String queryString, Class resultType); + /** + * Create an instance of {@link SelectionQuery} for the given HQL/JPQL + * query string. + * + * @param queryString The HQL/JPQL query + * + * @return The {@link SelectionQuery} instance for manipulation and execution + * + * @see jakarta.persistence.EntityManager#createQuery(String, Class) + */ + SelectionQuery createSelectionQuery(String queryString, Class resultType); + + /** + * Create an instance of {@link MutationQuery} for the given HQL/JPQL + * update or delete statement. + * + * @param queryString The HQL/JPQL query, update or delete statement + * + * @return The {@link MutationQuery} instance for manipulation and execution + * + * @see jakarta.persistence.EntityManager#createQuery(String) + */ + MutationQuery createMutationQuery(String queryString); + /** * Create an instance of {@link Query} for the given SQL query string, * or SQL update, insert, or delete statement. In the case of an update, diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java index 6e6ff1e0b..72ab5862a 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSessionImpl.java @@ -485,7 +485,7 @@ public EntityGraph createEntityGraph(Class rootType, String graphName) return delegate.createEntityGraph( rootType, graphName ); } - @Override + @Override @Deprecated public Query createQuery(String queryString) { return new StageQueryImpl<>( delegate.createReactiveQuery( queryString ) ); } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageStatelessSessionImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageStatelessSessionImpl.java index b37e381bd..51ccae294 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageStatelessSessionImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageStatelessSessionImpl.java @@ -225,11 +225,21 @@ public CompletionStage get(EntityGraph entityGraph, Object id) { return delegate.reactiveGet( entityClass, id, null, entityGraph ); } - @Override + @Override @Deprecated public Query createQuery(String queryString) { return new StageQueryImpl<>( delegate.createReactiveQuery( queryString ) ); } + @Override + public SelectionQuery createSelectionQuery(String queryString, Class resultType) { + return new StageSelectionQueryImpl<>( delegate.createReactiveSelectionQuery( queryString, resultType ) ); + } + + @Override + public MutationQuery createMutationQuery(String queryString) { + return new StageMutationQueryImpl<>( delegate.createReactiveMutationQuery( queryString ) ); + } + @Override public SelectionQuery createQuery(String queryString, Class resultType) { return new StageSelectionQueryImpl<>( delegate.createReactiveQuery( queryString, resultType ) ); From b92d99c15e458bef9c06c24150362f03806acffb Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 11 Jul 2023 14:02:25 +0200 Subject: [PATCH 08/14] fix a warning --- .../event/impl/DefaultReactiveDeleteEventListener.java | 4 ++-- .../org/hibernate/reactive/query/ReactiveSelectionQuery.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) 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 1d8a03951..2c7784d7b 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 @@ -128,8 +128,8 @@ public CompletionStage reactiveOnDelete(DeleteEvent event, DeleteContext t final EventSource source = event.getSession(); Object object = event.getObject(); if ( object instanceof CompletionStage ) { - final CompletionStage objectStage = (CompletionStage) object; - return objectStage.thenCompose( objectEvent -> fetchAndDelete( event, transientEntities, source, objectEvent ) ); + final CompletionStage stage = (CompletionStage) object; + return stage.thenCompose( objectEvent -> fetchAndDelete( event, transientEntities, source, objectEvent ) ); } else { return fetchAndDelete( event, transientEntities, source, object); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java index bd090cfd9..20ce1e954 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java @@ -64,6 +64,7 @@ default CompletionStage> getReactiveResultList() { @Override ReactiveSelectionQuery setTimeout(int timeout); + Integer getFetchSize(); ReactiveSelectionQuery setFetchSize(int fetchSize); From 91eef427ede220ed96c1e9803bfe88b815479407 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 25 Aug 2023 09:18:46 +0200 Subject: [PATCH 09/14] Fix latest compilation errors and warnings --- .../hibernate/reactive/common/Identifier.java | 162 +++++++++--------- .../query/ReactiveSelectionQuery.java | 2 +- .../sql/internal/ReactiveNativeQueryImpl.java | 2 +- .../sqm/internal/ReactiveQuerySqmImpl.java | 12 +- .../ReactiveSqmSelectionQueryImpl.java | 3 +- 5 files changed, 94 insertions(+), 87 deletions(-) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/common/Identifier.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/common/Identifier.java index 484c35064..f097e0dfc 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/common/Identifier.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/common/Identifier.java @@ -8,6 +8,7 @@ import org.hibernate.Incubating; import jakarta.persistence.metamodel.SingularAttribute; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -16,90 +17,89 @@ * Represents a value of an attribute that forms part of the * natural key of an entity. * - * @see org.hibernate.annotations.NaturalId - * * @param the owning entity class + * @see org.hibernate.annotations.NaturalId */ @Incubating public abstract class Identifier { - public abstract Id[] ids(); - - public abstract Map namedValues(); - - public static class Id extends Identifier { - private Id(SingularAttribute attribute, I id) { - this.id = id; - this.attributeName = attribute.getName(); - } - - private Id(String attributeName, Object id) { - this.attributeName = attributeName; - this.id = id; - } - - private final String attributeName; - private final Object id; - - public Object getId() { - return id; - } - - public String getAttributeName() { - return attributeName; - } - - @Override - public Id[] ids() { - return new Id[]{this}; - } - - @Override - public Map namedValues() { - return Collections.singletonMap(attributeName, id); - } - } - - public static class Composite extends Identifier { - Id[] ids; - - public Composite(Id[] ids) { - this.ids = ids; - } - - public Id[] getValues() { - return ids; - } - - @Override - public Id[] ids() { - return ids; - } - - @Override - public Map namedValues() { - Map namedValues = new HashMap<>(); - for (Id id : ids) { - namedValues.put( id.getAttributeName(), id.getId() ); - } - return namedValues; - } - } - - public static Id id(SingularAttribute attribute, I id) { - return new Id<>(attribute, id); - } - - public static Id id(String attributeName, Object id) { - return new Id<>(attributeName, id); - } - - public static Id id(Class entityClass, String attributeName, Object id) { - return new Id<>(attributeName, id); - } - - @SafeVarargs - public static Identifier composite(Id... ids) { - return new Composite<>(ids); - } + public abstract Id[] ids(); + + public abstract Map namedValues(); + + public static class Id extends Identifier { + private Id(SingularAttribute attribute, I id) { + this.id = id; + this.attributeName = attribute.getName(); + } + + private Id(String attributeName, Object id) { + this.attributeName = attributeName; + this.id = id; + } + + private final String attributeName; + private final Object id; + + public Object getId() { + return id; + } + + public String getAttributeName() { + return attributeName; + } + + @Override + public Id[] ids() { + return new Id[] {this}; + } + + @Override + public Map namedValues() { + return Collections.singletonMap( attributeName, id ); + } + } + + public static class Composite extends Identifier { + Id[] ids; + + public Composite(Id[] ids) { + this.ids = ids; + } + + public Id[] getValues() { + return ids; + } + + @Override + public Id[] ids() { + return ids; + } + + @Override + public Map namedValues() { + Map namedValues = new HashMap<>(); + for ( Id id : ids ) { + namedValues.put( id.getAttributeName(), id.getId() ); + } + return namedValues; + } + } + + public static Id id(SingularAttribute attribute, I id) { + return new Id<>( attribute, id ); + } + + public static Id id(String attributeName, Object id) { + return new Id<>( attributeName, id ); + } + + public static Id id(Class entityClass, String attributeName, Object id) { + return new Id<>( attributeName, id ); + } + + @SafeVarargs + public static Identifier composite(Id... ids) { + return new Composite<>( ids ); + } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java index 20ce1e954..581731b49 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/ReactiveSelectionQuery.java @@ -123,7 +123,7 @@ default CompletionStage> getReactiveResultList() { void applyGraph(RootGraphImplementor graph, GraphSemantic semantic); - void enableFetchProfile(String profileName); + ReactiveSelectionQuery enableFetchProfile(String profileName); @Override ReactiveSelectionQuery setParameter(String name, Object value); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java index 282312d55..7c076ae27 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sql/internal/ReactiveNativeQueryImpl.java @@ -743,7 +743,7 @@ public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { } @Override - public void enableFetchProfile(String profileName) { + public ReactiveNativeQueryImpl enableFetchProfile(String profileName) { throw new UnsupportedOperationException("A native SQL query cannot use fetch profiles"); } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java index 0edb66a11..4dcd2891c 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveQuerySqmImpl.java @@ -7,7 +7,12 @@ import java.lang.invoke.MethodHandles; import java.time.Instant; -import java.util.*; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletionStage; import java.util.stream.Stream; @@ -210,7 +215,7 @@ private List applyDistinct(SqmSelectStatement sqmStatement, boolean hasLim final int toIndex = max != -1 ? first + max : resultSize; - return list.subList( first, toIndex > resultSize ? resultSize : toIndex ); + return list.subList( first, Math.min( toIndex, resultSize ) ); } return list; } @@ -828,7 +833,8 @@ public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { } @Override - public void enableFetchProfile(String profileName) { + public ReactiveQuerySqmImpl enableFetchProfile(String profileName) { selectionQueryDelegate.enableFetchProfile( profileName ); + return this; } } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java index a19c1cadf..88cc98728 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/query/sqm/internal/ReactiveSqmSelectionQueryImpl.java @@ -590,7 +590,8 @@ public void applyGraph(RootGraphImplementor graph, GraphSemantic semantic) { } @Override - public void enableFetchProfile(String profileName) { + public ReactiveSqmSelectionQueryImpl enableFetchProfile(String profileName) { selectionQueryDelegate.enableFetchProfile( profileName ); + return this; } } From 14f1a10dd9624917cd9835881127dd50ff8aab66 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 25 Aug 2023 09:25:51 +0200 Subject: [PATCH 10/14] Use latest ORM snapshot available --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a935d495a..bd685d28b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,10 +29,10 @@ org.gradle.java.installations.auto-download=false #db = MSSQL # Enable the SonatypeOS maven repository (mainly for Vert.x snapshots) when present (value ignored) -#enableSonatypeOpenSourceSnapshotsRep = true +enableSonatypeOpenSourceSnapshotsRep = true # Enable the maven local repository (for local development when needed) when present (value ignored) -enableMavenLocalRepo = true +# enableMavenLocalRepo = true # Override default Hibernate ORM version hibernateOrmVersion = 6.3.0-SNAPSHOT From c015805e84db7abf28d4ed5b6fb291820fa72b41 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Sat, 26 Aug 2023 08:53:10 +0200 Subject: [PATCH 11/14] Fix field names for tests with boolean converter --- .../org/hibernate/reactive/schema/BasicTypesTestEntity.java | 4 ++-- .../reactive/types/BasicTypesAndCallbacksForAllDBsTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/BasicTypesTestEntity.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/BasicTypesTestEntity.java index 7ea3ada33..75567438d 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/BasicTypesTestEntity.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/BasicTypesTestEntity.java @@ -60,10 +60,10 @@ public class BasicTypesTestEntity { Byte fieldByte; @Convert(converter = org.hibernate.type.YesNoConverter.class) - Boolean booleanTrueFalse; + Boolean booleanYesNo; @Convert(converter = org.hibernate.type.TrueFalseConverter.class) - Boolean booleanYesNo; + Boolean booleanTrueFalse; @Convert(converter = org.hibernate.type.NumericBooleanConverter.class) Boolean booleanNumeric; diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/BasicTypesAndCallbacksForAllDBsTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/BasicTypesAndCallbacksForAllDBsTest.java index 3c816665c..9d8a34d9f 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/BasicTypesAndCallbacksForAllDBsTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/BasicTypesAndCallbacksForAllDBsTest.java @@ -564,10 +564,10 @@ private static class Basic { Byte fieldByte; @Convert(converter = org.hibernate.type.YesNoConverter.class) - Boolean booleanTrueFalse; + Boolean booleanYesNo; @Convert(converter = org.hibernate.type.TrueFalseConverter.class) - Boolean booleanYesNo; + Boolean booleanTrueFalse; @Convert(converter = org.hibernate.type.NumericBooleanConverter.class) Boolean booleanNumeric; From ef821a18624e0b2542ae095b739e0850205e9d4e Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Sat, 26 Aug 2023 09:02:03 +0200 Subject: [PATCH 12/14] Fix expected column type for MariaDB and MySQL With ORM 6.3 the boolean converter is mapped as a char. WIth ORM 6.2 it was an enum. --- .../java/org/hibernate/reactive/containers/MySQLDatabase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java index ac1d0d0fa..a8b3f0ed4 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/MySQLDatabase.java @@ -41,8 +41,8 @@ class MySQLDatabase implements TestableDatabase { expectedDBTypeForClass.put( Boolean.class, "bit" ); expectedDBTypeForClass.put( NumericBooleanConverter.class, "int" ); - expectedDBTypeForClass.put( YesNoConverter.class, "enum" ); - expectedDBTypeForClass.put( TrueFalseConverter.class, "enum" ); + expectedDBTypeForClass.put( YesNoConverter.class, "char" ); + expectedDBTypeForClass.put( TrueFalseConverter.class, "char" ); expectedDBTypeForClass.put( byte[].class, "varbinary" ); // expectedDBTypeForClass.put( TextType.class, "text" ); From f1de37851ca011c84bc5ef7ec17f8744a536ca9e Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 25 Aug 2023 08:19:38 +0200 Subject: [PATCH 13/14] [#1706] Add support for org.hibernate.query.Page --- .../org/hibernate/reactive/mutiny/Mutiny.java | 28 +++++----- .../reactive/mutiny/impl/MutinyQueryImpl.java | 30 +++++++---- .../mutiny/impl/MutinySelectionQueryImpl.java | 30 +++++++---- .../org/hibernate/reactive/stage/Stage.java | 51 +++++++++---------- .../reactive/stage/impl/StageQueryImpl.java | 25 ++++++--- .../stage/impl/StageSelectionQueryImpl.java | 25 ++++++--- 6 files changed, 113 insertions(+), 76 deletions(-) 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 954c8fbb1..2a1703a3d 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 @@ -6,12 +6,7 @@ package org.hibernate.reactive.mutiny; 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.Parameter; +import jakarta.persistence.*; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaDelete; import jakarta.persistence.criteria.CriteriaQuery; @@ -19,11 +14,7 @@ import jakarta.persistence.metamodel.Attribute; import jakarta.persistence.metamodel.Metamodel; import org.hibernate.Cache; -import org.hibernate.CacheMode; -import org.hibernate.Filter; -import org.hibernate.FlushMode; -import org.hibernate.Incubating; -import org.hibernate.LockMode; +import org.hibernate.*; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.collection.spi.AbstractPersistentCollection; import org.hibernate.collection.spi.PersistentCollection; @@ -32,6 +23,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.query.Page; import org.hibernate.reactive.common.AffectedEntities; import org.hibernate.reactive.common.Identifier; import org.hibernate.reactive.common.ResultSetMapping; @@ -48,9 +40,7 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.internal.util.LockModeConverter.convertToLockMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheRetrieveMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheStoreMode; +import static org.hibernate.jpa.internal.util.CacheModeHelper.*; /** * An API for Hibernate Reactive where non-blocking operations are @@ -141,6 +131,16 @@ interface SelectionQuery extends AbstractQuery { */ SelectionQuery setFirstResult(int firstResult); + /** + * Set the {@linkplain Page page} of results to return. + * + * @see Page + * + * @since 2.1 + */ + @Incubating + SelectionQuery setPage(Page page); + /** * @return the maximum number results, or {@link Integer#MAX_VALUE} * if not set diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java index a0d3494be..b09f76085 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinyQueryImpl.java @@ -5,24 +5,27 @@ */ package org.hibernate.reactive.mutiny.impl; -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.Parameter; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; +import org.hibernate.query.Page; +import org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny.Query; import org.hibernate.reactive.query.ReactiveQuery; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.function.Supplier; +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.Parameter; public class MutinyQueryImpl implements Query { @@ -121,6 +124,13 @@ public Query setFirstResult(int startPosition) { return this; } + @Override + public Mutiny.SelectionQuery setPage(Page page) { + setFirstResult( page.getFirstResult() ); + setMaxResults( page.getMaxResults() ); + return this; + } + @Override public CacheMode getCacheMode() { return delegate.getCacheMode(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java index 9275b3336..f9211f9de 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/mutiny/impl/MutinySelectionQueryImpl.java @@ -5,24 +5,27 @@ */ package org.hibernate.reactive.mutiny.impl; -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.Parameter; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; +import org.hibernate.query.Page; +import org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny.SelectionQuery; import org.hibernate.reactive.query.ReactiveSelectionQuery; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.function.Supplier; +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.Parameter; public class MutinySelectionQueryImpl implements SelectionQuery { private final MutinySessionFactoryImpl factory; @@ -114,6 +117,13 @@ public SelectionQuery setFirstResult(int startPosition) { return this; } + @Override + public Mutiny.SelectionQuery setPage(Page page) { + setMaxResults( page.getMaxResults() ); + setFirstResult( page.getFirstResult() ); + return this; + } + @Override public CacheMode getCacheMode() { return delegate.getCacheMode(); 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 b14297b8a..5e1eb367a 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 @@ -5,18 +5,15 @@ */ package org.hibernate.reactive.stage; -import java.lang.invoke.MethodHandles; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.function.BiFunction; -import java.util.function.Function; - +import jakarta.persistence.*; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaDelete; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.CriteriaUpdate; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.Metamodel; import org.hibernate.Cache; -import org.hibernate.CacheMode; -import org.hibernate.Filter; -import org.hibernate.FlushMode; -import org.hibernate.Incubating; -import org.hibernate.LockMode; +import org.hibernate.*; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.collection.spi.AbstractPersistentCollection; import org.hibernate.collection.spi.PersistentCollection; @@ -25,6 +22,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; import org.hibernate.proxy.HibernateProxy; +import org.hibernate.query.Page; import org.hibernate.reactive.common.AffectedEntities; import org.hibernate.reactive.common.Identifier; import org.hibernate.reactive.common.ResultSetMapping; @@ -34,25 +32,16 @@ import org.hibernate.reactive.util.impl.CompletionStages; import org.hibernate.stat.Statistics; -import jakarta.persistence.CacheRetrieveMode; -import jakarta.persistence.CacheStoreMode; -import jakarta.persistence.EntityGraph; -import jakarta.persistence.FlushModeType; -import jakarta.persistence.LockModeType; -import jakarta.persistence.Parameter; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaDelete; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.CriteriaUpdate; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.Metamodel; +import java.lang.invoke.MethodHandles; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.function.BiFunction; +import java.util.function.Function; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.internal.util.LockModeConverter.convertToLockMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheRetrieveMode; -import static org.hibernate.jpa.internal.util.CacheModeHelper.interpretCacheStoreMode; +import static org.hibernate.jpa.internal.util.CacheModeHelper.*; /** * An API for Hibernate Reactive where non-blocking operations are @@ -143,6 +132,16 @@ interface SelectionQuery extends AbstractQuery { */ SelectionQuery setFirstResult(int firstResult); + /** + * Set the {@linkplain Page page} of results to return. + * + * @see Page + * + * @since 2.1 + */ + @Incubating + SelectionQuery setPage(Page page); + /** * @return the maximum number results, or {@link Integer#MAX_VALUE} * if not set diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java index b072ee05a..ee0a73b71 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageQueryImpl.java @@ -5,23 +5,25 @@ */ package org.hibernate.reactive.stage.impl; -import jakarta.persistence.CacheRetrieveMode; -import jakarta.persistence.CacheStoreMode; -import jakarta.persistence.EntityGraph; -import jakarta.persistence.FlushModeType; -import jakarta.persistence.LockModeType; -import jakarta.persistence.Parameter; +import java.util.List; +import java.util.concurrent.CompletionStage; + import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; +import org.hibernate.query.Page; import org.hibernate.reactive.query.ReactiveQuery; import org.hibernate.reactive.stage.Stage; import org.hibernate.reactive.stage.Stage.Query; -import java.util.List; -import java.util.concurrent.CompletionStage; +import jakarta.persistence.CacheRetrieveMode; +import jakarta.persistence.CacheStoreMode; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.LockModeType; +import jakarta.persistence.Parameter; public class StageQueryImpl implements Query { private final ReactiveQuery delegate; @@ -113,6 +115,13 @@ public Query setFirstResult(int startPosition) { return this; } + @Override + public Stage.SelectionQuery setPage(Page page) { + setFirstResult( page.getFirstResult() ); + setMaxResults( page.getMaxResults() ); + return this; + } + @Override public CacheMode getCacheMode() { return delegate.getCacheMode(); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java index 62a3944ea..40e1eda9f 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/stage/impl/StageSelectionQueryImpl.java @@ -5,22 +5,24 @@ */ package org.hibernate.reactive.stage.impl; -import jakarta.persistence.CacheRetrieveMode; -import jakarta.persistence.CacheStoreMode; -import jakarta.persistence.EntityGraph; -import jakarta.persistence.FlushModeType; -import jakarta.persistence.LockModeType; -import jakarta.persistence.Parameter; +import java.util.List; +import java.util.concurrent.CompletionStage; + import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.RootGraphImplementor; +import org.hibernate.query.Page; import org.hibernate.reactive.query.ReactiveSelectionQuery; import org.hibernate.reactive.stage.Stage.SelectionQuery; -import java.util.List; -import java.util.concurrent.CompletionStage; +import jakarta.persistence.CacheRetrieveMode; +import jakarta.persistence.CacheStoreMode; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.LockModeType; +import jakarta.persistence.Parameter; public class StageSelectionQueryImpl implements SelectionQuery { private final ReactiveSelectionQuery delegate; @@ -112,6 +114,13 @@ public SelectionQuery setFirstResult(int startPosition) { return this; } + @Override + public SelectionQuery setPage(Page page) { + setMaxResults( page.getMaxResults() ); + setFirstResult( page.getFirstResult() ); + return this; + } + @Override public CacheMode getCacheMode() { return delegate.getCacheMode(); From 1030b13737846d18c49f025b35404f21f58f0607 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Mon, 28 Aug 2023 21:27:51 +0200 Subject: [PATCH 14/14] [#1706] Test org.hibernate.query.Page with filters --- .../reactive/FilterWithPaginationTest.java | 200 +++++++++++++++++- 1 file changed, 199 insertions(+), 1 deletion(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FilterWithPaginationTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FilterWithPaginationTest.java index 318dcf745..6cba81521 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FilterWithPaginationTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FilterWithPaginationTest.java @@ -31,9 +31,11 @@ import static java.util.concurrent.TimeUnit.MINUTES; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.query.Page.first; +import static org.hibernate.query.Page.page; /** - * Test the combination of filters, max results and first result. + * Test the combination of filters, max results, first result, and {@link org.hibernate.query.Page}. */ @Timeout(value = 10, timeUnit = MINUTES) @@ -77,6 +79,23 @@ public void testMaxResultsAndOffsetWithStageWithBasicQuery(VertxTestContext cont ); } + /** + * Sql server run different queries based if order-by is missing and there are no filters + */ + @Test + public void testMaxResultsAndOffsetWithStageWithBasicQueryAndPage(VertxTestContext context) { + test( context, openSession() + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_BASIC_QUERY ) + .setPage( page( 2, 0 ) ) + .getResultList() ) + // I cannot use the order-by, so I'm not sure which result it will return + .thenAccept( list -> { + assertThat( list ).containsAnyOf( margaret, nellie, hedy, rebeccaActress, rebeccaSinger ); + assertThat( list ).hasSize( 2 ); + } ) + ); + } + @Test public void testOffsetWithStageWithBasicQuery(VertxTestContext context) { test( context, openSession() @@ -91,6 +110,20 @@ public void testOffsetWithStageWithBasicQuery(VertxTestContext context) { ); } + @Test + public void testWithStageWithBasicQueryAndPage(VertxTestContext context) { + test( context, openSession() + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_BASIC_QUERY ) + .setPage( first( 3 ) ) + .getResultList() ) + // I cannot use the order-by, so I'm not sure which results it will return + .thenAccept( list -> { + assertThat( list ).containsAnyOf( margaret, nellie, hedy, rebeccaActress, rebeccaSinger ); + assertThat( list ).hasSize( 3 ); + } ) + ); + } + @Test public void testMaxResultsWithStageWithBasicQuery(VertxTestContext context) { test( context, openSession() @@ -105,6 +138,20 @@ public void testMaxResultsWithStageWithBasicQuery(VertxTestContext context) { ); } + @Test + public void testMaxResultsWithStageWithBasicQueryAndPage(VertxTestContext context) { + test( context, openSession() + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_BASIC_QUERY ) + .setPage( first( 4 ) ) + .getResultList() ) + // I cannot use the order-by, so I'm not sure which result it will return + .thenAccept( list -> { + assertThat( list ).containsAnyOf( margaret, nellie, hedy, rebeccaActress, rebeccaSinger ); + assertThat( list ).hasSize( 4 ); + } ) + ); + } + @Test public void testMaxResultsWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) @@ -115,6 +162,16 @@ public void testMaxResultsWithStage(VertxTestContext context) { ); } + @Test + public void testMaxResultsWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .thenAccept( list -> assertThat( list ).containsExactly( margaret, rebeccaActress ) ) + ); + } + @Test public void testMaxResultsWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) @@ -125,6 +182,16 @@ public void testMaxResultsWithMutiny(VertxTestContext context) { ); } + @Test + public void testMaxResultsWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( margaret, rebeccaActress ) ) + ); + } + @Test public void testFirstResultWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) @@ -135,6 +202,16 @@ public void testFirstResultWithStage(VertxTestContext context) { ); } + @Test + public void testFirstResultWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 2, 1 ) ) + .getResultList() ) + .thenAccept( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + @Test public void testFirstResultWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) @@ -145,6 +222,16 @@ public void testFirstResultWithMutiny(VertxTestContext context) { ); } + @Test + public void testFirstResultWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 2, 1 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsAndOffsetWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) @@ -156,6 +243,16 @@ public void testMaxResultsAndOffsetWithStage(VertxTestContext context) { ); } + @Test + public void testMaxResultsAndOffsetWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.IS_ALIVE_FILTER ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 2, 1 ) ) + .getResultList() ) + .thenAccept( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsAndOffsetWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) @@ -167,6 +264,16 @@ public void testMaxResultsAndOffsetWithMutiny(VertxTestContext context) { ); } + @Test + public void testMaxResultsAndOffsetWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.IS_ALIVE_FILTER ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 2, 1 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsForParameterizedFilterWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -177,6 +284,16 @@ public void testMaxResultsForParameterizedFilterWithStage(VertxTestContext conte ); } + @Test + public void testMaxResultsForParameterizedFilterWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .thenAccept( list -> assertThat( list ).containsExactly( rebeccaActress, rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsForParameterizedFilterWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -187,6 +304,16 @@ public void testMaxResultsForParameterizedFilterWithMutiny(VertxTestContext cont ); } + @Test + public void testMaxResultsForParameterizedFilterWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaActress, rebeccaSinger ) ) + ); + } + @Test public void testSingleResultMaxResultsForParameterizedFilterWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -197,6 +324,16 @@ public void testSingleResultMaxResultsForParameterizedFilterWithStage(VertxTestC ); } + @Test + public void testSingleResultMaxResultsForParameterizedFilterWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 1 ) ) + .getSingleResult() ) + .thenAccept( result -> assertThat( result ).isEqualTo( rebeccaActress ) ) + ); + } + @Test public void testSingleResultMaxResultsForParameterizedFilterWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -207,6 +344,16 @@ public void testSingleResultMaxResultsForParameterizedFilterWithMutiny(VertxTest ); } + @Test + public void testSingleResultMaxResultsForParameterizedFilterWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 1 ) ) + .getSingleResult() ) + .invoke( result -> assertThat( result ).isEqualTo( rebeccaActress ) ) + ); + } + @Test public void testFirstResultForParameterizedFilterWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -217,6 +364,16 @@ public void testFirstResultForParameterizedFilterWithStage(VertxTestContext cont ); } + @Test + public void testFirstResultForParameterizedFilterWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 1, 1 ) ) + .getResultList() + .thenAccept( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) ) + ); + } + @Test public void testFirstResultForParameterizedFilterWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -227,6 +384,16 @@ public void testFirstResultForParameterizedFilterWithMutiny(VertxTestContext con ); } + @Test + public void testFirstResultForParameterizedFilterWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 1, 1 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsAndFirstResultForParameterizedFilterWithStage(VertxTestContext context) { test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -238,6 +405,16 @@ public void testMaxResultsAndFirstResultForParameterizedFilterWithStage(VertxTes ); } + @Test + public void testMaxResultsAndFirstResultForParameterizedFilterWithStageAndPage(VertxTestContext context) { + test( context, enableFilter( openSession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .thenCompose( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .thenAccept( list -> assertThat( list ).containsExactly( rebeccaActress, rebeccaSinger ) ) + ); + } + @Test public void testMaxResultsAndFirstResultForParameterizedFilterWithMutiny(VertxTestContext context) { test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) @@ -249,6 +426,27 @@ public void testMaxResultsAndFirstResultForParameterizedFilterWithMutiny(VertxTe ); } + @Test + public void testMaxResultsAndFirstResultForParameterizedFilterWithMutinyAndPage(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( page( 1, 1 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaSinger ) ) + ); + } + + + @Test + public void testMaxResultsAndFirstResultForParameterizedFilterWithMutinyAndPageFirst(VertxTestContext context) { + test( context, enableFilter( openMutinySession(), FamousPerson.HAS_NAME_FILTER, "name", rebeccaActress.name ) + .chain( session -> session.createNamedQuery( FamousPerson.FIND_ALL_QUERY ) + .setPage( first( 2 ) ) + .getResultList() ) + .invoke( list -> assertThat( list ).containsExactly( rebeccaActress, rebeccaSinger ) ) + ); + } + private static CompletionStage enableFilter( CompletionStage stageSession, String filterName,