From bff18353d2fb6ee2759e93f27ed866858db66f8c Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 13 Jun 2022 17:30:00 +0100 Subject: [PATCH 1/9] [#929] Refactor id generation for MySQL MySQL always returns an id of type Long. This commit changes an hack that was affecting all dbs and preventing H2 to read identity id of type Integer or Short --- .../java/org/hibernate/reactive/logging/impl/Log.java | 4 ++-- .../entity/impl/ReactiveAbstractEntityPersister.java | 5 ----- .../reactive/pool/impl/SqlClientConnection.java | 11 ++++++++++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java index d3aa64278..eeec4ef9d 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/logging/impl/Log.java @@ -104,8 +104,8 @@ public interface Log extends BasicLogger { @Message(id = 34, value = "The database returned no natively generated identity value") HibernateException noNativelyGeneratedValueReturned(); - @Message(id = 35, value = "The database can only generate identifiers of type Long") - HibernateException nativelyGeneratedValueMustBeLong(); + @Message(id = 35, value = "The database can only generate identifiers of type Long: the id %1$d cannot be cast to %2$s ") + HibernateException nativelyGeneratedValueMustBeLong(Long id, @FormatWith(ClassFormatter.class) Class idClass); @Message(id = 356, value = "Wrong entity type!") HibernateException wrongEntityType(); 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 6d094e443..05420138e 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 @@ -393,11 +393,6 @@ default CompletionStage insertReactive( } ); Class idClass = delegate().getIdentifierType().getReturnedClass(); - if ( idClass.equals(Integer.class) || idClass.equals(Short.class) ) { - // since on MySQL we can only retrieve Long values, adjust to Long - // id will be cast back to the right type by castToIdentifierType() - idClass = Long.class; - } return getReactiveConnection( session ) //Note: in ORM core there are other ways to fetch the generated identity: // getGeneratedKeys(), or an extra round select statement. But we diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java index e5108d723..12e17a2a3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java @@ -309,10 +309,19 @@ public CompletionStage close() { private static T getLastInsertedId(RowSet rows, Class idClass, String idColumnName) { final Long mySqlId = rows.property( MYSQL_LAST_INSERTED_ID ); if ( mySqlId != null ) { + // MySQL will return a Long for any of these types if ( Long.class.equals( idClass ) ) { return (T) mySqlId; } - throw LOG.nativelyGeneratedValueMustBeLong(); + if ( Integer.class.equals( idClass ) + && mySqlId <= Integer.MAX_VALUE ) { + return (T) mySqlId; + } + if ( Short.class.equals( idClass ) + && mySqlId <= Short.MAX_VALUE) { + return (T) mySqlId; + } + throw LOG.nativelyGeneratedValueMustBeLong( mySqlId, idClass ); } final Row oracleKeys = rows.property( ORACLE_GENERATED_KEYS ); if ( oracleKeys != null ) { From 0a4946e2affac83b413bd190f3e390d5af05332c Mon Sep 17 00:00:00 2001 From: blafond Date: Wed, 6 Apr 2022 09:26:31 -0500 Subject: [PATCH 2/9] [#929] hibernate-reactive-h2 module --- hibernate-reactive-h2/build.gradle | 60 ++++++++++ .../jdbc/boot/impl/H2ServiceContributor.java | 18 +++ ...bcSqlClientPoolConfigurationInitiator.java | 29 +++++ .../hibernate/reactive/jdbc/package-info.java | 8 ++ .../pool/impl/H2ClientPoolConfiguration.java | 24 ++++ .../H2ReactiveConnectionPoolInitiator.java | 31 +++++ .../jdbc/pool/impl/H2SqlClientPool.java | 107 ++++++++++++++++++ .../impl/JdbcClientPoolConfiguration.java | 30 +++++ ...rnate.reactive.pool.ReactiveConnectionPool | 1 + ...g.hibernate.service.spi.ServiceContributor | 1 + 10 files changed, 309 insertions(+) create mode 100644 hibernate-reactive-h2/build.gradle create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/H2ServiceContributor.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/JdbcSqlClientPoolConfigurationInitiator.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/package-info.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ClientPoolConfiguration.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ReactiveConnectionPoolInitiator.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2SqlClientPool.java create mode 100644 hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/JdbcClientPoolConfiguration.java create mode 100644 hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.reactive.pool.ReactiveConnectionPool create mode 100644 hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.service.spi.ServiceContributor diff --git a/hibernate-reactive-h2/build.gradle b/hibernate-reactive-h2/build.gradle new file mode 100644 index 000000000..5ecd4666d --- /dev/null +++ b/hibernate-reactive-h2/build.gradle @@ -0,0 +1,60 @@ +ext { + mavenPomName = 'Hibernate Reactive H2' +} + +description = 'The H2 module of Hibernate Reactive' + +apply from: publishScript + +dependencies { + implementation project(':hibernate-reactive-core') + implementation "com.h2database:h2:2.1.214" + + // Dependencies for using H2 with Vert.x: + implementation "io.vertx:vertx-jdbc-client:${vertxVersion}" + + // Testing + testImplementation 'org.assertj:assertj-core:3.20.2' + testImplementation "io.vertx:vertx-unit:${vertxVersion}" + + // log4j + testRuntimeOnly 'org.apache.logging.log4j:log4j-core:2.17.1' +} + +// Print a summary of the results of the tests (number of failures, successes and skipped) +def loggingSummary(db, result, desc) { + if ( !desc.parent ) { // will match the outermost suite + def output = "${db} results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" + def repeatLength = output.length() + 1 + logger.lifecycle '\n' + ('-' * repeatLength) + '\n' + output + '\n' + ('-' * repeatLength) + } +} + +// Configuration for the tests +tasks.withType(Test) { + defaultCharacterEncoding = "UTF-8" + testLogging { + displayGranularity 1 + showStandardStreams = project.hasProperty('showStandardOutput') + showStackTraces = true + exceptionFormat = 'full' + events 'PASSED', 'FAILED', 'SKIPPED' + } + systemProperty 'org.hibernate.reactive.common.InternalStateAssertions.ENFORCE', 'true' + + if ( project.hasProperty( 'includeTests' ) ) { + // Example: ./gradlew testAll -PincludeTests=DefaultPortTest + filter { + includeTestsMatching project.getProperty( 'includeTests' ) ?: '*' + } + } +} + +test { + afterSuite { desc, result -> + loggingSummary( 'H2', result, desc ) + } + doFirst { + systemProperty 'db', 'H2' + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/H2ServiceContributor.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/H2ServiceContributor.java new file mode 100644 index 000000000..a3debfd22 --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/H2ServiceContributor.java @@ -0,0 +1,18 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.jdbc.boot.impl; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.reactive.jdbc.pool.impl.H2ReactiveConnectionPoolInitiator; +import org.hibernate.service.spi.ServiceContributor; + +public class H2ServiceContributor implements ServiceContributor { + @Override + public void contribute(StandardServiceRegistryBuilder serviceRegistryBuilder) { + serviceRegistryBuilder.addInitiator( H2ReactiveConnectionPoolInitiator.INSTANCE ); + serviceRegistryBuilder.addInitiator( JdbcSqlClientPoolConfigurationInitiator.INSTANCE ); + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/JdbcSqlClientPoolConfigurationInitiator.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/JdbcSqlClientPoolConfigurationInitiator.java new file mode 100644 index 000000000..f3e92df12 --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/boot/impl/JdbcSqlClientPoolConfigurationInitiator.java @@ -0,0 +1,29 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.jdbc.boot.impl; + +import java.util.Map; + +import org.hibernate.boot.registry.StandardServiceInitiator; +import org.hibernate.reactive.jdbc.pool.impl.H2ClientPoolConfiguration; +import org.hibernate.reactive.pool.impl.JdbcClientPoolConfiguration; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +public class JdbcSqlClientPoolConfigurationInitiator implements StandardServiceInitiator { + + public static final JdbcSqlClientPoolConfigurationInitiator INSTANCE = new JdbcSqlClientPoolConfigurationInitiator() { + }; + + @Override + public JdbcClientPoolConfiguration initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + return new H2ClientPoolConfiguration(); + } + + @Override + public Class getServiceInitiated() { + return JdbcClientPoolConfiguration.class; + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/package-info.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/package-info.java new file mode 100644 index 000000000..6996dc780 --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/package-info.java @@ -0,0 +1,8 @@ +/** +// * Hibernate Reactive is an adaptation of Hibernate ORM to the +// * world of reactive programming, and replaces JDBC for database +// * access with a non-blocking database client. +// *

+// *

+ */ +package org.hibernate.reactive.jdbc; diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ClientPoolConfiguration.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ClientPoolConfiguration.java new file mode 100644 index 000000000..97a19f64a --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ClientPoolConfiguration.java @@ -0,0 +1,24 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.jdbc.pool.impl; + +import java.net.URI; + +import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration; +import org.hibernate.reactive.pool.impl.JdbcClientPoolConfiguration; + +import io.vertx.core.json.JsonObject; + +public class H2ClientPoolConfiguration extends DefaultSqlClientPoolConfiguration implements JdbcClientPoolConfiguration { + + @Override + public JsonObject jdbcConnectOptions(URI uri) { + return new JsonObject() + .put( "url", uri.toString() ) + .put( "user", "sa" ) + .put( "pass", null ); + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ReactiveConnectionPoolInitiator.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ReactiveConnectionPoolInitiator.java new file mode 100644 index 000000000..949ea7703 --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2ReactiveConnectionPoolInitiator.java @@ -0,0 +1,31 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.jdbc.pool.impl; + +import java.util.Map; + +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.reactive.pool.ReactiveConnectionPool; +import org.hibernate.reactive.pool.impl.ReactiveConnectionPoolInitiator; +import org.hibernate.reactive.provider.Settings; +import org.hibernate.service.spi.ServiceRegistryImplementor; + +public class H2ReactiveConnectionPoolInitiator extends ReactiveConnectionPoolInitiator { + + public static final H2ReactiveConnectionPoolInitiator INSTANCE = new H2ReactiveConnectionPoolInitiator(); + + @Override + public ReactiveConnectionPool initiateService(Map configurationValues, ServiceRegistryImplementor registry) { + String url = ConfigurationHelper.getString( Settings.URL, configurationValues ); + // Check URL for H2 and return H2 specific pool + if ( url.startsWith( "jdbc:h2:" ) ) { + return new H2SqlClientPool(); + } + + // delegate to super class to initiate the DefaultSqlClientPool + return super.initiateService( configurationValues, registry ); + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2SqlClientPool.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2SqlClientPool.java new file mode 100644 index 000000000..8b9c49bd4 --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/H2SqlClientPool.java @@ -0,0 +1,107 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.jdbc.pool.impl; + + +import java.lang.invoke.MethodHandles; +import java.net.URI; +import java.util.Map; +import java.util.concurrent.CompletionStage; + +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.jdbc.spi.SqlStatementLogger; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.reactive.logging.impl.Log; +import org.hibernate.reactive.logging.impl.LoggerFactory; +import org.hibernate.reactive.pool.impl.JdbcClientPoolConfiguration; +import org.hibernate.reactive.pool.impl.SqlClientPool; +import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.vertx.VertxInstance; +import org.hibernate.service.spi.Configurable; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.Startable; +import org.hibernate.service.spi.Stoppable; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import io.vertx.jdbcclient.JDBCPool; +import io.vertx.sqlclient.Pool; + +public class H2SqlClientPool extends SqlClientPool + implements ServiceRegistryAwareService, Configurable, Stoppable, Startable { + + private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + + public static final String DEFAULT_URL = "jdbc:h2:mem:hreact"; + + //Asynchronous shutdown promise: we can't return it from #close as we implement a + //blocking interface. + private volatile Future closeFuture = Future.succeededFuture(); + + private Pool pools; + private URI uri; + private SqlStatementLogger sqlStatementLogger; + private ServiceRegistryImplementor serviceRegistry; + + public H2SqlClientPool() { + } + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.serviceRegistry = serviceRegistry; + sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger(); + } + + @Override + public void configure(Map configuration) { + uri = jdbcUrl( configuration ); + } + + protected URI jdbcUrl(Map configurationValues) { + String url = ConfigurationHelper.getString( Settings.URL, configurationValues, DEFAULT_URL ); + LOG.sqlClientUrl( url); + return URI.create( url ); + } + + @Override + public void start() { + if ( pools == null ) { + pools = createPool( uri ); + } + } + + @Override + public CompletionStage getCloseFuture() { + return closeFuture.toCompletionStage(); + } + + @Override + protected Pool getPool() { + return pools; + } + + private Pool createPool(URI uri) { + JdbcClientPoolConfiguration configuration = serviceRegistry.getService( JdbcClientPoolConfiguration.class ); + VertxInstance vertx = serviceRegistry.getService( VertxInstance.class ); + JsonObject poolOptions = configuration.poolOptions().toJson(); + JsonObject connectOptions = configuration.jdbcConnectOptions( uri ); + JsonObject config = poolOptions.mergeIn( connectOptions ); + return JDBCPool.pool( vertx.getVertx(), config ); + } + + @Override + public void stop() { + if ( pools != null ) { + this.closeFuture = pools.close(); + } + } + + @Override + protected SqlStatementLogger getSqlStatementLogger() { + return sqlStatementLogger; + } +} diff --git a/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/JdbcClientPoolConfiguration.java b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/JdbcClientPoolConfiguration.java new file mode 100644 index 000000000..dabbc78ad --- /dev/null +++ b/hibernate-reactive-h2/src/main/java/org/hibernate/reactive/jdbc/pool/impl/JdbcClientPoolConfiguration.java @@ -0,0 +1,30 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.pool.impl; + +import java.net.URI; + +import org.hibernate.service.Service; + +import io.vertx.core.json.JsonObject; +import io.vertx.sqlclient.PoolOptions; + +public interface JdbcClientPoolConfiguration extends Service { + /** + * The {@link PoolOptions} used to configure the {@code Pool} + */ + PoolOptions poolOptions(); + + /** + * The {@link JsonObject} used to configure the {@code Pool} + * + * @param uri A {@link URI} representing the JDBC URL or connection URI + * specified in the configuration properties, usually via + * {@link org.hibernate.cfg.Environment#JPA_JDBC_URL}, or + * {@code null} if not specified. + */ + JsonObject jdbcConnectOptions(URI uri); +} diff --git a/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.reactive.pool.ReactiveConnectionPool b/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.reactive.pool.ReactiveConnectionPool new file mode 100644 index 000000000..09ac42fda --- /dev/null +++ b/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.reactive.pool.ReactiveConnectionPool @@ -0,0 +1 @@ +org.hibernate.reactive.jdbc.pool.impl.H2SqlClientPool \ No newline at end of file diff --git a/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.service.spi.ServiceContributor b/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.service.spi.ServiceContributor new file mode 100644 index 000000000..bc90093cb --- /dev/null +++ b/hibernate-reactive-h2/src/main/resources/META-INF/services/org.hibernate.service.spi.ServiceContributor @@ -0,0 +1 @@ +org.hibernate.reactive.jdbc.boot.impl.H2ServiceContributor \ No newline at end of file From 4888ea24ede1e6ea8fa856b4548b6689dd6762c4 Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 13 Jun 2022 18:22:54 +0100 Subject: [PATCH 3/9] [#929] H2 --- hibernate-reactive-core/build.gradle | 4 +++- .../adaptor/impl/ResultSetAdaptor.java | 20 +++++++++++++++- .../DefaultSqlClientPoolConfiguration.java | 8 +++++++ .../pool/impl/SqlClientConnection.java | 24 ++++++++++++------- .../service/NoJdbcEnvironmentInitiator.java | 6 ++++- settings.gradle | 1 + 6 files changed, 52 insertions(+), 11 deletions(-) diff --git a/hibernate-reactive-core/build.gradle b/hibernate-reactive-core/build.gradle index f685c0e1e..3f64c0c7e 100644 --- a/hibernate-reactive-core/build.gradle +++ b/hibernate-reactive-core/build.gradle @@ -31,6 +31,8 @@ dependencies { testImplementation 'org.assertj:assertj-core:3.22.0' testImplementation "io.vertx:vertx-unit:${vertxVersion}" + testImplementation project(':hibernate-reactive-h2') + // Drivers testImplementation "io.vertx:vertx-pg-client:${vertxVersion}" testImplementation "io.vertx:vertx-mysql-client:${vertxVersion}" @@ -139,7 +141,7 @@ tasks.addRule( "Pattern testDb" ) { String taskName -> } // The dbs we want to test when running testAll -def dbs = ['MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle'] +def dbs = ['MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle', 'H2'] task testAll( dependsOn: dbs.collect( [] as HashSet ) { db -> "testDb${db}" } ) { description = "Run tests for ${dbs}" } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/adaptor/impl/ResultSetAdaptor.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/adaptor/impl/ResultSetAdaptor.java index 077c7d32e..59f2550c6 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/adaptor/impl/ResultSetAdaptor.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/adaptor/impl/ResultSetAdaptor.java @@ -45,13 +45,31 @@ */ public class ResultSetAdaptor implements ResultSet { + private static final class EmptyRowIterator implements RowIterator { + + public static final EmptyRowIterator INSTANCE = new EmptyRowIterator(); + + private EmptyRowIterator() { + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Row next() { + return null; + } + } + private final RowIterator iterator; private final RowSet rows; private Row row; private boolean wasNull; public ResultSetAdaptor(RowSet rows) { - this.iterator = rows.iterator(); + this.iterator = rows != null ? rows.iterator() : EmptyRowIterator.INSTANCE; this.rows = rows; } diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java index 2e114d4bc..01917edd7 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/DefaultSqlClientPoolConfiguration.java @@ -49,6 +49,14 @@ public class DefaultSqlClientPoolConfiguration implements SqlClientPoolConfigura private String user; private String pass; + protected String getUser() { + return user; + } + + protected String getPassword() { + return pass; + } + @Override public void configure(Map configuration) { user = getString( Settings.USER, configuration ); diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java index 12e17a2a3..105eda2fa 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/pool/impl/SqlClientConnection.java @@ -95,12 +95,16 @@ public CompletionStage selectIdentifier(String sql, Object[] paramValues, translateNulls( paramValues ); return preparedQuery( sql, Tuple.wrap( paramValues ) ) .handle( (rows, throwable) -> convertException( rows, sql, throwable ) ) - .thenApply( rowSet -> { - for (Row row: rowSet) { - return row.get(idClass, 0); - } - return null; - } ); + .thenApply( rowSet -> identifierFromFirstRow( idClass, rowSet ) ); + } + + private T identifierFromFirstRow(Class idClass, RowSet rowSet) { + if ( rowSet != null ) { + for ( Row row : rowSet ) { + return row.get( idClass, 0 ); + } + } + return null; } @Override @@ -170,7 +174,11 @@ public CompletionStage update(String sql) { } public CompletionStage update(String sql, Tuple parameters) { - return preparedQuery( sql, parameters ).thenApply(SqlResult::rowCount); + return preparedQuery( sql, parameters ).thenApply( SqlClientConnection::rowCount ); + } + + private static Integer rowCount(RowSet rows) { + return rows == null ? 0 : rows.rowCount(); } public CompletionStage updateBatch(String sql, List parametersBatch) { @@ -180,7 +188,7 @@ public CompletionStage updateBatch(String sql, List parametersBatc int i = 0; RowSet resultNext = result; - if ( parametersBatch.size() > 0 ) { + if ( result != null && parametersBatch.size() > 0 ) { final RowIterator iterator = resultNext.iterator(); if ( iterator.hasNext() ) { while ( iterator.hasNext() ) { diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java index e1975380f..49e7b31b2 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/provider/service/NoJdbcEnvironmentInitiator.java @@ -9,6 +9,7 @@ import org.hibernate.dialect.CockroachDB201Dialect; import org.hibernate.dialect.DB297Dialect; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.MariaDB103Dialect; import org.hibernate.dialect.MySQL8Dialect; import org.hibernate.dialect.Oracle12cDialect; @@ -35,7 +36,7 @@ /** * A Hibernate {@link StandardServiceInitiator service initiator} that * provides an implementation of {@link JdbcEnvironment} that infers - * the Hibernate {@link org.hibernate.dialect.Dialect} from the JDBC URL. + * the Hibernate {@link Dialect} from the JDBC URL. */ public class NoJdbcEnvironmentInitiator extends JdbcEnvironmentInitiator { private static final Log LOG = LoggerFactory.make( Log.class, MethodHandles.lookup() ); @@ -147,6 +148,9 @@ else if ( url.startsWith( "sqlserver:" ) ) { else if ( url.startsWith( "oracle:" ) ) { return Oracle12cDialect.class; } + else if ( url.startsWith( "h2:" ) ) { + return H2Dialect.class; + } else { return null; } diff --git a/settings.gradle b/settings.gradle index 9cf1fbd00..07d980b89 100644 --- a/settings.gradle +++ b/settings.gradle @@ -82,6 +82,7 @@ logger.lifecycle "Java versions for main code: " + gradle.ext.javaVersions.main logger.lifecycle "Java versions for tests: " + gradle.ext.javaVersions.test include 'hibernate-reactive-core' +include 'hibernate-reactive-h2' include 'session-example' include 'native-sql-example' include 'verticle-postgres-it' From 4794c7800779ed40ecf3d8dc4e25d6bd105d2ef0 Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 13 Jun 2022 17:44:44 +0100 Subject: [PATCH 4/9] [#929] Add H2Database --- .../reactive/containers/H2Database.java | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java new file mode 100644 index 000000000..68e6f90f5 --- /dev/null +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java @@ -0,0 +1,144 @@ +/* Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.reactive.containers; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; +import java.util.UUID; + +import org.hibernate.type.NumericBooleanType; +import org.hibernate.type.TextType; +import org.hibernate.type.TrueFalseType; +import org.hibernate.type.YesNoType; +import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor; + +public class H2Database implements TestableDatabase { + public static H2Database INSTANCE = new H2Database(); + + private static Map, String> expectedDBTypeForClass = new HashMap<>(); + + static { + { + expectedDBTypeForClass.put( boolean.class, "BOOLEAN" ); + expectedDBTypeForClass.put( Boolean.class, "BOOLEAN" ); + expectedDBTypeForClass.put( NumericBooleanType.class, "INTEGER" ); + expectedDBTypeForClass.put( TrueFalseType.class, "CHARACTER" ); + expectedDBTypeForClass.put( YesNoType.class, "CHARACTER" ); + expectedDBTypeForClass.put( int.class, "INTEGER" ); + expectedDBTypeForClass.put( Integer.class, "INTEGER" ); + expectedDBTypeForClass.put( long.class, "BIGINT" ); + expectedDBTypeForClass.put( Long.class, "BIGINT" ); + expectedDBTypeForClass.put( float.class, "DOUBLE PRECISION" ); + expectedDBTypeForClass.put( Float.class, "DOUBLE PRECISION" ); + expectedDBTypeForClass.put( double.class, "DOUBLE PRECISION" ); + expectedDBTypeForClass.put( Double.class, "DOUBLE PRECISION" ); + expectedDBTypeForClass.put( byte.class, "TINYINT" ); + expectedDBTypeForClass.put( Byte.class, "TINYINT" ); + expectedDBTypeForClass.put( PrimitiveByteArrayTypeDescriptor.class, "BINARY VARYING" ); + expectedDBTypeForClass.put( URL.class, "CHARACTER VARYING" ); + expectedDBTypeForClass.put( TimeZone.class, "CHARACTER VARYING" ); + expectedDBTypeForClass.put( Date.class, "DATE" ); + expectedDBTypeForClass.put( Timestamp.class, "TIMESTAMP" ); + expectedDBTypeForClass.put( Time.class, "TIME" ); + expectedDBTypeForClass.put( LocalDate.class, "DATE" ); + expectedDBTypeForClass.put( LocalTime.class, "time" ); + expectedDBTypeForClass.put( LocalDateTime.class, "TIMESTAMP" ); + expectedDBTypeForClass.put( BigInteger.class, "NUMERIC" ); + expectedDBTypeForClass.put( BigDecimal.class, "NUMERIC" ); + expectedDBTypeForClass.put( Serializable.class, "BINARY VARYING" ); + expectedDBTypeForClass.put( UUID.class, "binary" ); + expectedDBTypeForClass.put( Instant.class, "datetime" ); + expectedDBTypeForClass.put( Duration.class, "bigint" ); + expectedDBTypeForClass.put( Character.class, "VARCHAR_IGNORECASE" ); + expectedDBTypeForClass.put( char.class, "VARCHAR_IGNORECASE" ); + expectedDBTypeForClass.put( TextType.class, "text" ); + expectedDBTypeForClass.put( String.class, "CHARACTER VARYING" ); + } + } + + @Override + public String getJdbcUrl() { + return "jdbc:" + getUri(); + } + + @Override + public String getUri() { + return "h2:~/test;DATABASE_TO_UPPER=FALSE"; + } + + + @Override + public String getScheme() { + return "h2:"; + } + + @Override + public String getNativeDatatypeQuery(String tableName, String columnName) { + return "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS COLS " + + "WHERE COLS.TABLE_NAME = '" + tableName + "'" + + "AND COLS.COLUMN_NAME= '" + columnName + "'"; + } + + @Override + public String getExpectedNativeDatatype(Class dataType) { + return expectedDBTypeForClass.get( dataType ); + } + + @Override + public String createJdbcUrl(String host, int port, String database, Map params) { + // Primary mode for H2 is embedded which uses the URL format: "jdbc:h2:~/test" + // H2 can also be configured as a remote server. + // EXAMPLE 1: jdbc:h2:tcp://localhost/D:/myproject/data/project-name + // EXAMPLE 2: jdbc:h2:tcp://localhost/~/test + // EXAMpLE 3: jdbc:h2:tcp://localhost:9081/~/test + final StringBuilder paramsBuilder = new StringBuilder(); + if ( params != null && !params.isEmpty() ) { + params.forEach( (key, value) -> { + paramsBuilder.append( jdbcParamDelimiter() ); + paramsBuilder.append( key ); + paramsBuilder.append( "=" ); + paramsBuilder.append( value ); + } ); + } + String url = "jdbc:" + getScheme() + "//" + host; + if ( port > -1 ) { + url += ":" + port; + } + if ( paramsBuilder.length() > 0 ) { + url += jdbcStartQuery() + paramsBuilder.substring( 1 ); + } + if ( database != null ) { + return url + ";database=" + database; + } + return url; + } + + @Override + public String jdbcStartQuery() { + return ";"; + } + + @Override + public String jdbcParamDelimiter() { + return ";"; + } + + private H2Database() { + } +} From 13dbcccd39aeb707bbd0562bc48227c6a9d26dc0 Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 13 Jun 2022 17:45:28 +0100 Subject: [PATCH 5/9] [#929] Adapt or disable existing tests for H2 --- .../java/org/hibernate/reactive/DefaultPortTest.java | 6 ++++++ .../test/java/org/hibernate/reactive/FormulaTest.java | 3 ++- .../org/hibernate/reactive/MutinyExceptionsTest.java | 11 ++++++++++- .../java/org/hibernate/reactive/UUIDAsBinaryType.java | 5 +++-- .../java/org/hibernate/reactive/UriConfigTest.java | 6 ++++++ .../org/hibernate/reactive/WrongCredentialsTest.java | 6 ++++++ .../reactive/configuration/JdbcUrlParserTest.java | 6 ++++++ .../reactive/containers/DatabaseConfiguration.java | 3 ++- .../reactive/schema/SchemaUpdateTestBase.java | 3 ++- .../reactive/schema/SchemaValidationTestBase.java | 3 ++- .../org/hibernate/reactive/types/JsonTypeTest.java | 3 ++- .../reactive/types/StringToJsonTypeTest.java | 3 ++- .../hibernate/reactive/types/UserJsonTypeTest.java | 3 ++- 13 files changed, 51 insertions(+), 10 deletions(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java index 13d54b4d6..293a7f2b6 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/DefaultPortTest.java @@ -14,13 +14,16 @@ import org.hibernate.reactive.containers.DatabaseConfiguration; import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration; import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.testing.DatabaseSelectionRule; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; import io.vertx.sqlclient.SqlConnectOptions; import org.assertj.core.api.Assertions; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; /** @@ -28,6 +31,9 @@ */ public class DefaultPortTest { + @Rule + public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( H2 ); + @Test public void testDefaultPortIsSet() throws URISyntaxException { DefaultSqlClientPoolConfiguration configuration = new DefaultSqlClientPoolConfiguration(); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FormulaTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FormulaTest.java index 699164b46..2e866cc3f 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FormulaTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/FormulaTest.java @@ -22,13 +22,14 @@ import java.util.Collection; import java.util.List; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MYSQL; public class FormulaTest extends BaseReactiveTest { @Rule - public DatabaseSelectionRule rule = DatabaseSelectionRule.skipTestsFor( MARIA, MYSQL ); + public DatabaseSelectionRule rule = DatabaseSelectionRule.skipTestsFor( MARIA, MYSQL, H2 ); @Override protected Collection> annotatedEntities() { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinyExceptionsTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinyExceptionsTest.java index 3790dcd2a..d02b96455 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinyExceptionsTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/MutinyExceptionsTest.java @@ -15,12 +15,16 @@ import org.hibernate.HibernateException; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; +import org.hibernate.reactive.containers.DatabaseConfiguration; +import org.hibernate.reactive.exception.ConstraintViolationException; import org.hibernate.reactive.mutiny.Mutiny; import org.junit.Test; import io.vertx.ext.unit.TestContext; +import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; + public class MutinyExceptionsTest extends BaseReactiveTest { @Override @@ -48,7 +52,12 @@ public void testDuplicateKeyException(TestContext context) { .onItem().call( Mutiny.Session::flush ) .onItem().invoke( ignore -> context.fail( "Expected exception not thrown" ) ) .onFailure().recoverWithItem( err -> { - context.assertEquals( getExpectedException(), err.getClass() ); + if( dbType() == DatabaseConfiguration.DBType.H2 ) { + context.assertTrue( ConstraintViolationException.class == err.getClass() || + getExpectedException() == err.getClass() ); + } else { + context.assertEquals( getExpectedException(), err.getClass() ); + } return null; } ) ); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UUIDAsBinaryType.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UUIDAsBinaryType.java index 3078b79ef..e31b33424 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UUIDAsBinaryType.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UUIDAsBinaryType.java @@ -22,6 +22,7 @@ import io.vertx.ext.unit.TestContext; import static java.util.Arrays.asList; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MYSQL; import static org.hibernate.reactive.testing.DatabaseSelectionRule.runOnlyFor; @@ -103,8 +104,8 @@ public String toString() { public static class ForOtherDbsTest extends UUIDAsBinaryType { - @Rule - public DatabaseSelectionRule rule = skipTestsFor( MYSQL, MARIA ); + @Rule // Select a UUID field doesn't work with Oracle + public DatabaseSelectionRule rule = skipTestsFor( MYSQL, MARIA, H2 ); @Override protected Collection> annotatedEntities() { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java index 7a0c96a0a..1996fe469 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/UriConfigTest.java @@ -17,15 +17,21 @@ import org.hibernate.dialect.SQLServer2012Dialect; import org.hibernate.reactive.containers.DatabaseConfiguration; import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.testing.DatabaseSelectionRule; +import org.junit.Rule; import org.junit.Test; import io.vertx.ext.unit.TestContext; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; public class UriConfigTest extends BaseReactiveTest { + @Rule + public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( H2 ); + @Override protected Configuration constructConfiguration() { Class dialect; diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongCredentialsTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongCredentialsTest.java index 2cddf24d7..bc8d53d59 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongCredentialsTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/WrongCredentialsTest.java @@ -11,12 +11,15 @@ import org.hibernate.cfg.Configuration; import org.hibernate.reactive.containers.DatabaseConfiguration; import org.hibernate.reactive.provider.Settings; +import org.hibernate.reactive.testing.DatabaseSelectionRule; +import org.junit.Rule; import org.junit.Test; import io.vertx.ext.unit.TestContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; /** * Check that the right exception is thrown when there is an error with the credentials. @@ -28,6 +31,9 @@ */ public class WrongCredentialsTest extends BaseReactiveTest { + @Rule + public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( H2 ); + @Override protected Configuration constructConfiguration() { Configuration configuration = super.constructConfiguration(); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java index 51b679062..99e972dac 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/configuration/JdbcUrlParserTest.java @@ -12,13 +12,16 @@ import org.hibernate.HibernateError; import org.hibernate.reactive.pool.impl.DefaultSqlClientPool; import org.hibernate.reactive.pool.impl.DefaultSqlClientPoolConfiguration; +import org.hibernate.reactive.testing.DatabaseSelectionRule; +import org.junit.Rule; import org.junit.Test; import io.vertx.sqlclient.SqlConnectOptions; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.createJdbcUrl; import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; import static org.junit.Assert.assertThrows; @@ -33,6 +36,9 @@ public class JdbcUrlParserTest { private static final String DEFAULT_DB = "hreactDB"; + @Rule + public DatabaseSelectionRule rule = DatabaseSelectionRule.skipTestsFor( H2 ); + @Test public void exceptionWhenNull() { final HibernateError error = assertThrows( HibernateError.class, () -> { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java index 3bd7f11b2..7584ebf38 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/DatabaseConfiguration.java @@ -25,7 +25,8 @@ public enum DBType { POSTGRESQL( PostgreSQLDatabase.INSTANCE, 5432, "POSTGRES", "PG" ), COCKROACHDB( CockroachDBDatabase.INSTANCE, 26257, "COCKROACH" ), SQLSERVER( MSSQLServerDatabase.INSTANCE, 1433, "MSSQL", "MSSQLSERVER" ), - ORACLE( OracleDatabase.INSTANCE, 1521 ); + ORACLE( OracleDatabase.INSTANCE, 1521 ), + H2( H2Database.INSTANCE, -1 ); private final TestableDatabase configuration; private final int defaultPort; diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaUpdateTestBase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaUpdateTestBase.java index 692e63d26..b0dac7d0e 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaUpdateTestBase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaUpdateTestBase.java @@ -21,6 +21,7 @@ import io.vertx.ext.unit.TestContext; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; import static org.hibernate.reactive.containers.DatabaseConfiguration.dbType; import static org.hibernate.tool.schema.JdbcMetadaAccessStrategy.GROUPED; @@ -53,7 +54,7 @@ protected Configuration constructConfiguration(String hbm2DdlOption) { } @Rule - public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( DB2 ); + public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( DB2, H2 ); protected Configuration constructConfiguration(String action) { Configuration configuration = super.constructConfiguration(); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTestBase.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTestBase.java index 8b67e2b35..9afdaf537 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTestBase.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/schema/SchemaValidationTestBase.java @@ -12,6 +12,7 @@ import javax.persistence.Table; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.tool.schema.JdbcMetadaAccessStrategy.GROUPED; import static org.hibernate.tool.schema.JdbcMetadaAccessStrategy.INDIVIDUALLY; @@ -59,7 +60,7 @@ protected Configuration constructConfiguration(String hbm2DdlOption) { } @Rule - public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( DB2 ); + public DatabaseSelectionRule dbRule = DatabaseSelectionRule.skipTestsFor( DB2, H2 ); protected Configuration constructConfiguration(String action) { Configuration configuration = super.constructConfiguration(); diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java index be7446d90..83a9b08ce 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/JsonTypeTest.java @@ -25,6 +25,7 @@ import io.vertx.ext.unit.TestContext; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; @@ -34,7 +35,7 @@ public class JsonTypeTest extends BaseReactiveTest { @Rule - public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, ORACLE); + public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, ORACLE, H2); @Override protected Collection> annotatedEntities() { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/StringToJsonTypeTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/StringToJsonTypeTest.java index 992e7f656..916e5d190 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/StringToJsonTypeTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/StringToJsonTypeTest.java @@ -25,6 +25,7 @@ import java.util.function.Consumer; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.MARIA; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; @@ -35,7 +36,7 @@ public class StringToJsonTypeTest extends BaseReactiveTest { @Rule - public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, MARIA, ORACLE ); + public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, MARIA, ORACLE, H2 ); @Override protected Collection> annotatedEntities() { diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/UserJsonTypeTest.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/UserJsonTypeTest.java index fa8e1165e..907a2d942 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/UserJsonTypeTest.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/types/UserJsonTypeTest.java @@ -27,6 +27,7 @@ import io.vertx.ext.unit.TestContext; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.DB2; +import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.H2; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.ORACLE; import static org.hibernate.reactive.containers.DatabaseConfiguration.DBType.SQLSERVER; @@ -36,7 +37,7 @@ public class UserJsonTypeTest extends BaseReactiveTest { @Rule - public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, ORACLE ); + public DatabaseSelectionRule selectionRule = DatabaseSelectionRule.skipTestsFor( DB2, SQLSERVER, ORACLE, H2 ); @Override protected Collection> annotatedEntities() { From 6ebda19462373d3ac99f295e1506082d6b5096ee Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 13 Jun 2022 18:08:02 +0100 Subject: [PATCH 6/9] [#929] Add H2 to the GitHub workflows --- .github/workflows/build.yml | 2 +- .github/workflows/tracking-orm-5.build.yml | 3 +-- .github/workflows/tracking-vertx-4.build.yml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6448af365..a488dcb18 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,7 +98,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle' ] + db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle', 'H2' ] steps: - uses: actions/checkout@v2 - name: Get year/month for cache key diff --git a/.github/workflows/tracking-orm-5.build.yml b/.github/workflows/tracking-orm-5.build.yml index 27fcf2c2d..05e880ced 100644 --- a/.github/workflows/tracking-orm-5.build.yml +++ b/.github/workflows/tracking-orm-5.build.yml @@ -89,7 +89,7 @@ jobs: strategy: matrix: orm-version: [ '[5.6,5.7)' ] - db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle' ] + db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle', 'H2' ] steps: - uses: actions/checkout@v2 - name: Set up JDK 11 @@ -100,4 +100,3 @@ jobs: run: ./gradlew :hibernate-reactive-core:dependencyInsight --dependency org.hibernate:hibernate-core -PhibernateOrmVersion='${{ matrix.orm-version }}' -PskipOrmVersionParsing -PenableJBossSnapshotsRep - name: Build and Test with ${{ matrix.db }} run: ./gradlew build -Pdb=${{ matrix.db }} -Pdocker -PhibernateOrmVersion='${{ matrix.orm-version }}' -PskipOrmVersionParsing -PenableJBossSnapshotsRep -PshowStandardOutput - diff --git a/.github/workflows/tracking-vertx-4.build.yml b/.github/workflows/tracking-vertx-4.build.yml index fa97abfb6..2e018f176 100644 --- a/.github/workflows/tracking-vertx-4.build.yml +++ b/.github/workflows/tracking-vertx-4.build.yml @@ -87,7 +87,7 @@ jobs: strategy: matrix: vertx-version: [ '[4.2,4.4)' ] - db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle' ] + db: [ 'MariaDB', 'MySQL', 'PostgreSQL', 'DB2', 'CockroachDB', 'MSSQLServer', 'Oracle', 'H2' ] steps: - uses: actions/checkout@v2 - name: Set up JDK 11 From 6c3a488cfc6c7662487febdd8c24986775d70221 Mon Sep 17 00:00:00 2001 From: Davide Date: Tue, 14 Jun 2022 23:32:09 +0100 Subject: [PATCH 7/9] Add ;DB_CLOSE_DELAY=-1 to testing url --- .../test/java/org/hibernate/reactive/containers/H2Database.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java index 68e6f90f5..783bd2869 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java @@ -79,7 +79,7 @@ public String getJdbcUrl() { @Override public String getUri() { - return "h2:~/test;DATABASE_TO_UPPER=FALSE"; + return "h2:~/test;DATABASE_TO_UPPER=FALSE;DB_CLOSE_DELAY=-1"; } From 31e554f884d781529c002533559722a382ee179d Mon Sep 17 00:00:00 2001 From: Davide Date: Tue, 14 Jun 2022 23:43:15 +0100 Subject: [PATCH 8/9] Remove unused import --- .../persister/entity/impl/ReactiveAbstractEntityPersister.java | 1 - 1 file changed, 1 deletion(-) 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 05420138e..71da65d90 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 @@ -62,7 +62,6 @@ import org.hibernate.reactive.session.ReactiveConnectionSupplier; import org.hibernate.reactive.session.ReactiveSession; import org.hibernate.reactive.stage.Stage; -import org.hibernate.reactive.stage.impl.StageSessionFactoryImpl; import org.hibernate.reactive.stage.impl.StageSessionImpl; import org.hibernate.reactive.tuple.MutinyValueGenerator; import org.hibernate.reactive.tuple.StageValueGenerator; From 9bee7beeeee2fda27e963bce05b870514cf5f491 Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Wed, 22 Jun 2022 22:35:14 +0100 Subject: [PATCH 9/9] Use H2 in memory as default --- .../test/java/org/hibernate/reactive/containers/H2Database.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java index 783bd2869..0a4835a6f 100644 --- a/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java +++ b/hibernate-reactive-core/src/test/java/org/hibernate/reactive/containers/H2Database.java @@ -79,7 +79,7 @@ public String getJdbcUrl() { @Override public String getUri() { - return "h2:~/test;DATABASE_TO_UPPER=FALSE;DB_CLOSE_DELAY=-1"; + return "h2:mem:test;DATABASE_TO_UPPER=FALSE;DB_CLOSE_DELAY=-1"; }