From a571dbe03c04991361ace4eaeaeeee2352e81921 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Thu, 11 Aug 2022 10:57:07 +0300 Subject: [PATCH] Add support for Testcontainers #476 --- README.md | 8 +- hibernate-types-4/pom.xml | 4 +- .../AbstractContainerDataSourceProvider.java | 48 +++++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 51 ++++++----- .../providers/OracleDataSourceProvider.java | 35 +++++--- .../PostgreSQLDataSourceProvider.java | 21 +++-- .../SQLServerDataSourceProvider.java | 35 +++++--- hibernate-types-43/pom.xml | 4 +- .../AbstractContainerDataSourceProvider.java | 48 +++++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 51 ++++++----- .../providers/OracleDataSourceProvider.java | 35 +++++--- .../PostgreSQLDataSourceProvider.java | 21 +++-- .../SQLServerDataSourceProvider.java | 35 +++++--- hibernate-types-5/pom.xml | 4 +- .../AbstractContainerDataSourceProvider.java | 48 +++++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 51 ++++++----- .../providers/OracleDataSourceProvider.java | 34 +++++--- .../PostgreSQLDataSourceProvider.java | 21 +++-- .../SQLServerDataSourceProvider.java | 35 +++++--- .../AbstractContainerDataSourceProvider.java | 48 +++++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 60 ++++++------- .../providers/OracleDataSourceProvider.java | 34 +++++--- .../PostgreSQLDataSourceProvider.java | 25 +++--- .../SQLServerDataSourceProvider.java | 31 ++++--- .../SpringDataJPABaseConfiguration.java | 28 ++---- .../SpringDataJPASaveConfiguration.java | 1 - .../resources/META-INF/jdbc-hsqldb.properties | 6 -- .../resources/META-INF/jdbc-mysql.properties | 6 -- .../META-INF/jdbc-postgresql.properties | 8 -- .../AbstractContainerDataSourceProvider.java | 39 +++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 44 +++++----- .../providers/OracleDataSourceProvider.java | 34 +++++--- .../PostgreSQLDataSourceProvider.java | 25 +++--- .../SQLServerDataSourceProvider.java | 31 ++++--- .../SpringDataJPABaseConfiguration.java | 28 ++---- .../SpringDataJPASaveConfiguration.java | 1 - .../resources/META-INF/jdbc-hsqldb.properties | 6 -- .../resources/META-INF/jdbc-mysql.properties | 6 -- .../META-INF/jdbc-postgresql.properties | 8 -- hibernate-types-60/pom.xml | 1 + .../AbstractContainerDataSourceProvider.java | 39 +++++++++ .../hibernate/util/providers/Database.java | 85 +++++++++++++++++-- .../providers/MySQLDataSourceProvider.java | 60 ++++++------- .../providers/OracleDataSourceProvider.java | 35 +++++--- .../PostgreSQLDataSourceProvider.java | 22 +++-- .../SQLServerDataSourceProvider.java | 31 ++++--- pom.xml | 47 +++++++++- 52 files changed, 1280 insertions(+), 523 deletions(-) create mode 100644 hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java create mode 100644 hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java create mode 100644 hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java create mode 100644 hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java delete mode 100644 hibernate-types-52/src/test/resources/META-INF/jdbc-hsqldb.properties delete mode 100644 hibernate-types-52/src/test/resources/META-INF/jdbc-mysql.properties delete mode 100644 hibernate-types-52/src/test/resources/META-INF/jdbc-postgresql.properties create mode 100644 hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java delete mode 100644 hibernate-types-55/src/test/resources/META-INF/jdbc-hsqldb.properties delete mode 100644 hibernate-types-55/src/test/resources/META-INF/jdbc-mysql.properties delete mode 100644 hibernate-types-55/src/test/resources/META-INF/jdbc-postgresql.properties create mode 100644 hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java diff --git a/README.md b/README.md index 81bc46755..9f7f586a8 100644 --- a/README.md +++ b/README.md @@ -378,12 +378,16 @@ Or, if you prefer reading books, you are going to love my [High-Performance Java #### Contributing Guide -The project uses [Maven Toolchains](https://maven.apache.org/guides/mini/guide-using-toolchains.html) as different modules are compiled and tested using different Java versions. Hibernate Types 6 requires Java 17 while Hibernate Types 4 compiles with Java 1.6. +The project uses [Maven Toolchains](https://maven.apache.org/guides/mini/guide-using-toolchains.html) as different modules are compiled and tested using different Java versions. Hibernate Types 6 requires Java 17 while the other modules are compiled with either Java 1.8 or 1.6. To see how to configure Maven Toolchains, check out [this article](https://vladmihalcea.com/maven-and-java-multi-version-modules/). The project uses various database systems for integration testing, and you can configure the JDBC connection settings using the -`DatasourceProvider` instances (e.g., `PostgreSQLDataSourceProvider`). +`DatasourceProvider` instances (e.g., `PostgreSQLDataSourceProvider`), and the project uses Testcontainers to bootstrap a Docker container +with the required Oracle, SQL Server, PostgreSQL, or MySQL instance on demand. + +> If you are a regular contributor, it's advisable to set up the required database locally or use the Docker Compose configuration provided in the `docker` folder, +> as bootstrapping the containers on demand is slower, and your tests are going to take longer to run. If you want to fix an issue or add support for a new feature, please provide the associated integration test case that proves the improvement is working as expected. diff --git a/hibernate-types-4/pom.xml b/hibernate-types-4/pom.xml index 148ad8562..ed2947eb8 100644 --- a/hibernate-types-4/pom.xml +++ b/hibernate-types-4/pom.xml @@ -34,7 +34,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} provided true @@ -77,7 +77,7 @@ 4.2.21.Final 9.4-1202-jdbc4 - 2.7.9.6 + 2.12.6.1 12.0 1.4.2 diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..57f6aace9 --- /dev/null +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,48 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + Connection connection = null; + try { + connection = dataSource.getConnection(); + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException ignore) { + } + } + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index eb6d5f4f4..23d921f14 100644 --- a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -8,7 +8,7 @@ /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -76,19 +76,19 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode - - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); + return dataSource; } @@ -101,22 +101,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override @@ -127,12 +124,12 @@ public Database database() { @Override public String toString() { return "MySQLDataSourceProvider{" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - ", cachePrepStmts=" + cachePrepStmts + - ", useServerPrepStmts=" + useServerPrepStmts + - ", useTimezone=" + useTimezone + - ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + - '}'; + "rewriteBatchedStatements=" + rewriteBatchedStatements + + ", cachePrepStmts=" + cachePrepStmts + + ", useServerPrepStmts=" + useServerPrepStmts + + ", useTimezone=" + useTimezone + + ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + + ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + + '}'; } } diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index f2b3b67bc..6db0ced32 100644 --- a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,7 +1,8 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.Oracle10gDialect; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -9,20 +10,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return Oracle10gDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -31,7 +43,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -44,11 +56,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index 779c72473..4a6f0f854 100644 --- a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -9,7 +9,7 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { @@ -17,12 +17,16 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setUrl(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -41,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index a7ceab4fe..632aecb54 100644 --- a/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-4/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -1,6 +1,7 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -8,25 +9,36 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return "org.hibernate.dialect.SQLServer2012Dialect"; } @Override - public DataSource dataSource() { - DataSource dataSource = ReflectionUtils.newInstance("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); - ReflectionUtils.invokeMethod(dataSource, "setURL", "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;"); - ReflectionUtils.invokeMethod(dataSource, "setUser", "sa"); - ReflectionUtils.invokeMethod(dataSource, "setPassword", "adm1n"); + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { + SQLServerDataSource dataSource = new SQLServerDataSource(); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); + return SQLServerDataSource.class; } @Override @@ -36,11 +48,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/hibernate-types-43/pom.xml b/hibernate-types-43/pom.xml index e7e6a5c1a..ae508bfd9 100644 --- a/hibernate-types-43/pom.xml +++ b/hibernate-types-43/pom.xml @@ -34,7 +34,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} provided true @@ -77,7 +77,7 @@ 4.3.11.Final 9.4-1202-jdbc4 - 2.7.9.6 + 2.12.6.1 12.0 1.4.2 diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..57f6aace9 --- /dev/null +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,48 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + Connection connection = null; + try { + connection = dataSource.getConnection(); + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException ignore) { + } + } + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index eb6d5f4f4..23d921f14 100644 --- a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -8,7 +8,7 @@ /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -76,19 +76,19 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode - - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); + return dataSource; } @@ -101,22 +101,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override @@ -127,12 +124,12 @@ public Database database() { @Override public String toString() { return "MySQLDataSourceProvider{" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - ", cachePrepStmts=" + cachePrepStmts + - ", useServerPrepStmts=" + useServerPrepStmts + - ", useTimezone=" + useTimezone + - ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + - '}'; + "rewriteBatchedStatements=" + rewriteBatchedStatements + + ", cachePrepStmts=" + cachePrepStmts + + ", useServerPrepStmts=" + useServerPrepStmts + + ", useTimezone=" + useTimezone + + ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + + ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + + '}'; } } diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index f2b3b67bc..6db0ced32 100644 --- a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,7 +1,8 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.Oracle10gDialect; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -9,20 +10,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return Oracle10gDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -31,7 +43,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -44,11 +56,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index b184b0098..d4475eab1 100644 --- a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -9,7 +9,7 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { @@ -17,12 +17,16 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setUrl(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -41,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index a7ceab4fe..632aecb54 100644 --- a/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-43/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -1,6 +1,7 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -8,25 +9,36 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return "org.hibernate.dialect.SQLServer2012Dialect"; } @Override - public DataSource dataSource() { - DataSource dataSource = ReflectionUtils.newInstance("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); - ReflectionUtils.invokeMethod(dataSource, "setURL", "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;"); - ReflectionUtils.invokeMethod(dataSource, "setUser", "sa"); - ReflectionUtils.invokeMethod(dataSource, "setPassword", "adm1n"); + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { + SQLServerDataSource dataSource = new SQLServerDataSource(); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); + return SQLServerDataSource.class; } @Override @@ -36,11 +48,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/hibernate-types-5/pom.xml b/hibernate-types-5/pom.xml index fc242f664..c388c0917 100644 --- a/hibernate-types-5/pom.xml +++ b/hibernate-types-5/pom.xml @@ -34,7 +34,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} provided true @@ -77,7 +77,7 @@ 5.1.17.Final 9.4-1202-jdbc4 - 2.7.9.6 + 2.12.6.1 12.0 1.4.2 diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..57f6aace9 --- /dev/null +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,48 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + Connection connection = null; + try { + connection = dataSource.getConnection(); + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException ignore) { + } + } + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index eb6d5f4f4..23d921f14 100644 --- a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -8,7 +8,7 @@ /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -76,19 +76,19 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode - - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); + return dataSource; } @@ -101,22 +101,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override @@ -127,12 +124,12 @@ public Database database() { @Override public String toString() { return "MySQLDataSourceProvider{" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - ", cachePrepStmts=" + cachePrepStmts + - ", useServerPrepStmts=" + useServerPrepStmts + - ", useTimezone=" + useTimezone + - ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + - '}'; + "rewriteBatchedStatements=" + rewriteBatchedStatements + + ", cachePrepStmts=" + cachePrepStmts + + ", useServerPrepStmts=" + useServerPrepStmts + + ", useTimezone=" + useTimezone + + ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + + ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + + '}'; } } diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index ca44ba501..0f75d867d 100644 --- a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,11 +1,13 @@ package com.vladmihalcea.hibernate.util.providers; import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -13,20 +15,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return EnhancedOracle12cDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -35,7 +48,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -48,11 +61,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index ee5da1f23..a2a1b26a7 100644 --- a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -9,7 +9,7 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { @@ -17,12 +17,16 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setUrl(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -41,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index a7ceab4fe..632aecb54 100644 --- a/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-5/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -1,6 +1,7 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -8,25 +9,36 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return "org.hibernate.dialect.SQLServer2012Dialect"; } @Override - public DataSource dataSource() { - DataSource dataSource = ReflectionUtils.newInstance("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); - ReflectionUtils.invokeMethod(dataSource, "setURL", "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;"); - ReflectionUtils.invokeMethod(dataSource, "setUser", "sa"); - ReflectionUtils.invokeMethod(dataSource, "setPassword", "adm1n"); + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { + SQLServerDataSource dataSource = new SQLServerDataSource(); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("com.microsoft.sqlserver.jdbc.SQLServerDataSource"); + return SQLServerDataSource.class; } @Override @@ -36,11 +48,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..57f6aace9 --- /dev/null +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,48 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + Connection connection = null; + try { + connection = dataSource.getConnection(); + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException ignore) { + } + } + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index 669fbb2c6..a0824ecd6 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -3,12 +3,13 @@ import com.mysql.cj.jdbc.MysqlDataSource; import javax.sql.DataSource; +import java.sql.SQLException; import java.util.Properties; /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -76,20 +77,24 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { - MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode - - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); - return dataSource; + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { + try { + MysqlDataSource dataSource = new MysqlDataSource(); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); + + return dataSource; + } catch (SQLException e) { + throw new IllegalStateException("The DataSource could not be instantiated!"); + } } @Override @@ -101,22 +106,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override @@ -127,12 +129,12 @@ public Database database() { @Override public String toString() { return "MySQLDataSourceProvider{" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - ", cachePrepStmts=" + cachePrepStmts + - ", useServerPrepStmts=" + useServerPrepStmts + - ", useTimezone=" + useTimezone + - ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + - '}'; + "rewriteBatchedStatements=" + rewriteBatchedStatements + + ", cachePrepStmts=" + cachePrepStmts + + ", useServerPrepStmts=" + useServerPrepStmts + + ", useTimezone=" + useTimezone + + ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + + ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + + '}'; } } diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index ca44ba501..0f75d867d 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,11 +1,13 @@ package com.vladmihalcea.hibernate.util.providers; import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -13,20 +15,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return EnhancedOracle12cDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -35,7 +48,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -48,11 +61,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index 8dadc37b1..6dd6eb22f 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -1,6 +1,6 @@ package com.vladmihalcea.hibernate.util.providers; -import org.hibernate.dialect.PostgreSQL95Dialect; +import org.hibernate.dialect.PostgreSQL10Dialect; import org.postgresql.ds.PGSimpleDataSource; import javax.sql.DataSource; @@ -9,20 +9,24 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { - return PostgreSQL95Dialect.class.getName(); + return PostgreSQL10Dialect.class.getName(); } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -41,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index 62a1ace79..632aecb54 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -1,6 +1,7 @@ package com.vladmihalcea.hibernate.util.providers; import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -8,21 +9,30 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return "org.hibernate.dialect.SQLServer2012Dialect"; } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { SQLServerDataSource dataSource = new SQLServerDataSource(); - dataSource.setURL( - "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;" - ); - dataSource.setUser("sa"); - dataSource.setPassword("adm1n"); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @@ -38,11 +48,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java b/hibernate-types-52/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java index 808c37e86..b44c7db96 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java @@ -1,12 +1,13 @@ package com.vladmihalcea.spring.base.config; import com.vladmihalcea.hibernate.util.logging.InlineQueryLogEntryCreator; +import com.vladmihalcea.hibernate.util.providers.DataSourceProvider; +import com.vladmihalcea.hibernate.util.providers.PostgreSQLDataSourceProvider; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener; import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; import org.hibernate.jpa.HibernatePersistenceProvider; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @@ -32,20 +33,7 @@ @EnableAspectJAutoProxy public abstract class SpringDataJPABaseConfiguration { - @Value("${jdbc.dataSourceClassName}") - private String dataSourceClassName; - - @Value("${jdbc.url}") - private String jdbcUrl; - - @Value("${jdbc.username}") - private String jdbcUser; - - @Value("${jdbc.password}") - private String jdbcPassword; - - @Value("${hibernate.dialect}") - private String hibernateDialect; + private DataSourceProvider dataSourceProvider = new PostgreSQLDataSourceProvider(); @Bean public static PropertySourcesPlaceholderConfigurer propertySources() { @@ -54,17 +42,11 @@ public static PropertySourcesPlaceholderConfigurer propertySources() { @Bean(destroyMethod = "close") public HikariDataSource actualDataSource() { - Properties driverProperties = new Properties(); - driverProperties.setProperty("url", jdbcUrl); - driverProperties.setProperty("user", jdbcUser); - driverProperties.setProperty("password", jdbcPassword); - Properties properties = new Properties(); - properties.put("dataSourceClassName", dataSourceClassName); - properties.put("dataSourceProperties", driverProperties); properties.setProperty("maximumPoolSize", String.valueOf(3)); HikariConfig hikariConfig = new HikariConfig(properties); hikariConfig.setAutoCommit(false); + hikariConfig.setDataSource(dataSourceProvider.dataSource()); return new HikariDataSource(hikariConfig); } @@ -113,7 +95,7 @@ public JdbcTemplate jdbcTemplate(DataSource dataSource) { protected Properties properties() { Properties properties = new Properties(); - properties.setProperty("hibernate.dialect", hibernateDialect); + properties.setProperty("hibernate.dialect", dataSourceProvider.hibernateDialect()); properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); additionalProperties(properties); return properties; diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java b/hibernate-types-52/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java index 571340dc7..e2cc56601 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java @@ -18,7 +18,6 @@ } ) @EnableJpaRepositories("com.vladmihalcea.spring.repository") -@PropertySource({"/META-INF/jdbc-postgresql.properties"}) public class SpringDataJPASaveConfiguration extends SpringDataJPABaseConfiguration { @Override diff --git a/hibernate-types-52/src/test/resources/META-INF/jdbc-hsqldb.properties b/hibernate-types-52/src/test/resources/META-INF/jdbc-hsqldb.properties deleted file mode 100644 index 54dcea523..000000000 --- a/hibernate-types-52/src/test/resources/META-INF/jdbc-hsqldb.properties +++ /dev/null @@ -1,6 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.HSQLDialect -jdbc.driverClassName=org.hsqldb.jdbc.JDBCDriver -jdbc.dataSourceClassName=org.hsqldb.jdbc.JDBCDataSource -jdbc.url=jdbc:hsqldb:mem:test -jdbc.username=sa -jdbc.password= \ No newline at end of file diff --git a/hibernate-types-52/src/test/resources/META-INF/jdbc-mysql.properties b/hibernate-types-52/src/test/resources/META-INF/jdbc-mysql.properties deleted file mode 100644 index a47e83a03..000000000 --- a/hibernate-types-52/src/test/resources/META-INF/jdbc-mysql.properties +++ /dev/null @@ -1,6 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.MySQL57Dialect -jdbc.dataSourceClassName=com.mysql.cj.jdbc.MysqlDataSource -jdbc.url=jdbc:mysql://localhost/high_performance_java_persistence -jdbc.database=high_performance_java_persistence -jdbc.username=mysql -jdbc.password=admin \ No newline at end of file diff --git a/hibernate-types-52/src/test/resources/META-INF/jdbc-postgresql.properties b/hibernate-types-52/src/test/resources/META-INF/jdbc-postgresql.properties deleted file mode 100644 index cf95c16d5..000000000 --- a/hibernate-types-52/src/test/resources/META-INF/jdbc-postgresql.properties +++ /dev/null @@ -1,8 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect -jdbc.dataSourceClassName=org.postgresql.ds.PGSimpleDataSource -jdbc.url=jdbc:postgresql://localhost:5432/high_performance_java_persistence -jdbc.host=localhost -jdbc.port=5432 -jdbc.database=high_performance_java_persistence -jdbc.username=postgres -jdbc.password=admin \ No newline at end of file diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..44ef6fc57 --- /dev/null +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,39 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + try(Connection connection = dataSource.getConnection()) { + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index 669fbb2c6..9c3afd322 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -3,12 +3,13 @@ import com.mysql.cj.jdbc.MysqlDataSource; import javax.sql.DataSource; +import java.sql.SQLException; import java.util.Properties; /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -76,20 +77,24 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { - MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { + try { + MysqlDataSource dataSource = new MysqlDataSource(); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); - return dataSource; + return dataSource; + } catch (SQLException e) { + throw new IllegalStateException("The DataSource could not be instantiated!"); + } } @Override @@ -101,22 +106,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index ca44ba501..0f75d867d 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,11 +1,13 @@ package com.vladmihalcea.hibernate.util.providers; import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -13,20 +15,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return EnhancedOracle12cDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -35,7 +48,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -48,11 +61,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index 8dadc37b1..6dd6eb22f 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -1,6 +1,6 @@ package com.vladmihalcea.hibernate.util.providers; -import org.hibernate.dialect.PostgreSQL95Dialect; +import org.hibernate.dialect.PostgreSQL10Dialect; import org.postgresql.ds.PGSimpleDataSource; import javax.sql.DataSource; @@ -9,20 +9,24 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { - return PostgreSQL95Dialect.class.getName(); + return PostgreSQL10Dialect.class.getName(); } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -41,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index 62a1ace79..632aecb54 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -1,6 +1,7 @@ package com.vladmihalcea.hibernate.util.providers; import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -8,21 +9,30 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return "org.hibernate.dialect.SQLServer2012Dialect"; } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { SQLServerDataSource dataSource = new SQLServerDataSource(); - dataSource.setURL( - "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;" - ); - dataSource.setUser("sa"); - dataSource.setPassword("adm1n"); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @@ -38,11 +48,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java b/hibernate-types-55/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java index 808c37e86..b44c7db96 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/spring/base/config/SpringDataJPABaseConfiguration.java @@ -1,12 +1,13 @@ package com.vladmihalcea.spring.base.config; import com.vladmihalcea.hibernate.util.logging.InlineQueryLogEntryCreator; +import com.vladmihalcea.hibernate.util.providers.DataSourceProvider; +import com.vladmihalcea.hibernate.util.providers.PostgreSQLDataSourceProvider; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener; import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder; import org.hibernate.jpa.HibernatePersistenceProvider; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @@ -32,20 +33,7 @@ @EnableAspectJAutoProxy public abstract class SpringDataJPABaseConfiguration { - @Value("${jdbc.dataSourceClassName}") - private String dataSourceClassName; - - @Value("${jdbc.url}") - private String jdbcUrl; - - @Value("${jdbc.username}") - private String jdbcUser; - - @Value("${jdbc.password}") - private String jdbcPassword; - - @Value("${hibernate.dialect}") - private String hibernateDialect; + private DataSourceProvider dataSourceProvider = new PostgreSQLDataSourceProvider(); @Bean public static PropertySourcesPlaceholderConfigurer propertySources() { @@ -54,17 +42,11 @@ public static PropertySourcesPlaceholderConfigurer propertySources() { @Bean(destroyMethod = "close") public HikariDataSource actualDataSource() { - Properties driverProperties = new Properties(); - driverProperties.setProperty("url", jdbcUrl); - driverProperties.setProperty("user", jdbcUser); - driverProperties.setProperty("password", jdbcPassword); - Properties properties = new Properties(); - properties.put("dataSourceClassName", dataSourceClassName); - properties.put("dataSourceProperties", driverProperties); properties.setProperty("maximumPoolSize", String.valueOf(3)); HikariConfig hikariConfig = new HikariConfig(properties); hikariConfig.setAutoCommit(false); + hikariConfig.setDataSource(dataSourceProvider.dataSource()); return new HikariDataSource(hikariConfig); } @@ -113,7 +95,7 @@ public JdbcTemplate jdbcTemplate(DataSource dataSource) { protected Properties properties() { Properties properties = new Properties(); - properties.setProperty("hibernate.dialect", hibernateDialect); + properties.setProperty("hibernate.dialect", dataSourceProvider.hibernateDialect()); properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); additionalProperties(properties); return properties; diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java b/hibernate-types-55/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java index 571340dc7..e2cc56601 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/spring/repository/config/SpringDataJPASaveConfiguration.java @@ -18,7 +18,6 @@ } ) @EnableJpaRepositories("com.vladmihalcea.spring.repository") -@PropertySource({"/META-INF/jdbc-postgresql.properties"}) public class SpringDataJPASaveConfiguration extends SpringDataJPABaseConfiguration { @Override diff --git a/hibernate-types-55/src/test/resources/META-INF/jdbc-hsqldb.properties b/hibernate-types-55/src/test/resources/META-INF/jdbc-hsqldb.properties deleted file mode 100644 index 54dcea523..000000000 --- a/hibernate-types-55/src/test/resources/META-INF/jdbc-hsqldb.properties +++ /dev/null @@ -1,6 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.HSQLDialect -jdbc.driverClassName=org.hsqldb.jdbc.JDBCDriver -jdbc.dataSourceClassName=org.hsqldb.jdbc.JDBCDataSource -jdbc.url=jdbc:hsqldb:mem:test -jdbc.username=sa -jdbc.password= \ No newline at end of file diff --git a/hibernate-types-55/src/test/resources/META-INF/jdbc-mysql.properties b/hibernate-types-55/src/test/resources/META-INF/jdbc-mysql.properties deleted file mode 100644 index a47e83a03..000000000 --- a/hibernate-types-55/src/test/resources/META-INF/jdbc-mysql.properties +++ /dev/null @@ -1,6 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.MySQL57Dialect -jdbc.dataSourceClassName=com.mysql.cj.jdbc.MysqlDataSource -jdbc.url=jdbc:mysql://localhost/high_performance_java_persistence -jdbc.database=high_performance_java_persistence -jdbc.username=mysql -jdbc.password=admin \ No newline at end of file diff --git a/hibernate-types-55/src/test/resources/META-INF/jdbc-postgresql.properties b/hibernate-types-55/src/test/resources/META-INF/jdbc-postgresql.properties deleted file mode 100644 index cf95c16d5..000000000 --- a/hibernate-types-55/src/test/resources/META-INF/jdbc-postgresql.properties +++ /dev/null @@ -1,8 +0,0 @@ -hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect -jdbc.dataSourceClassName=org.postgresql.ds.PGSimpleDataSource -jdbc.url=jdbc:postgresql://localhost:5432/high_performance_java_persistence -jdbc.host=localhost -jdbc.port=5432 -jdbc.database=high_performance_java_persistence -jdbc.username=postgres -jdbc.password=admin \ No newline at end of file diff --git a/hibernate-types-60/pom.xml b/hibernate-types-60/pom.xml index 6a5d2ca86..b1630100f 100644 --- a/hibernate-types-60/pom.xml +++ b/hibernate-types-60/pom.xml @@ -96,6 +96,7 @@ 11 + 11 6.0.2.Final 42.4.1 diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java new file mode 100644 index 000000000..44ef6fc57 --- /dev/null +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/AbstractContainerDataSourceProvider.java @@ -0,0 +1,39 @@ +package com.vladmihalcea.hibernate.util.providers; + +import org.testcontainers.containers.JdbcDatabaseContainer; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Vlad Mihalcea + */ +public abstract class AbstractContainerDataSourceProvider implements DataSourceProvider { + + @Override + public DataSource dataSource() { + DataSource dataSource = newDataSource(); + try(Connection connection = dataSource.getConnection()) { + return dataSource; + } catch (SQLException e) { + Database database = database(); + if(database.getContainer() == null) { + database.initContainer(username(), password()); + } + return newDataSource(); + } + } + + @Override + public String url() { + JdbcDatabaseContainer container = database().getContainer(); + return container != null ? + container.getJdbcUrl() : + defaultJdbcUrl(); + } + + protected abstract String defaultJdbcUrl(); + + protected abstract DataSource newDataSource(); +} diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java index 9dd694070..006ed77dd 100644 --- a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/Database.java @@ -1,14 +1,89 @@ package com.vladmihalcea.hibernate.util.providers; +import org.testcontainers.containers.*; + +import java.util.Collections; + /** * @author Vlad Mihalcea */ public enum Database { HSQLDB, H2, - POSTGRESQL, - ORACLE, - MYSQL, - SQLSERVER, - COCKROACHDB + POSTGRESQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new PostgreSQLContainer("postgres:13.7"); + } + }, + ORACLE { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new OracleContainer("gvenzl/oracle-xe:21.3.0-slim"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + }, + MYSQL { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MySQLContainer("mysql:8.0"); + } + }, + SQLSERVER { + @Override + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + return new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2019-latest"); + } + + @Override + protected boolean supportsDatabaseName() { + return false; + } + + @Override + protected boolean supportsCredentials() { + return false; + } + }, + COCKROACHDB; + + private JdbcDatabaseContainer container; + + public JdbcDatabaseContainer getContainer() { + return container; + } + + public void initContainer(String username, String password) { + container = (JdbcDatabaseContainer) newJdbcDatabaseContainer() + .withEnv(Collections.singletonMap("ACCEPT_EULA", "Y")); + if(supportsDatabaseName()) { + container.withDatabaseName("high-performance-java-persistence"); + } + if(supportsCredentials()) { + container.withUsername(username).withPassword(password); + } + container.withTmpFs(Collections.singletonMap("/testtmpfs", "rw")); + container.start(); + } + + protected JdbcDatabaseContainer newJdbcDatabaseContainer() { + throw new UnsupportedOperationException( + String.format( + "The [%s] database was not configured to use Testcontainers!", + name() + ) + ); + } + + protected boolean supportsDatabaseName() { + return true; + } + + protected boolean supportsCredentials() { + return true; + } } diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java index 1cfff00fa..b9f33e3e0 100644 --- a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/MySQLDataSourceProvider.java @@ -4,12 +4,13 @@ import org.hibernate.dialect.MySQLDialect; import javax.sql.DataSource; +import java.sql.SQLException; import java.util.Properties; /** * @author Vlad Mihalcea */ -public class MySQLDataSourceProvider implements DataSourceProvider { +public class MySQLDataSourceProvider extends AbstractContainerDataSourceProvider { private boolean rewriteBatchedStatements = true; @@ -77,20 +78,24 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { - MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setURL("jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false&" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - "&cachePrepStmts=" + cachePrepStmts + - "&useServerPrepStmts=" + useServerPrepStmts + - "&useTimezone=" + useTimezone + - "&useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - "&useLegacyDatetimeCode=" + useLegacyDatetimeCode - - ); - dataSource.setUser("mysql"); - dataSource.setPassword("admin"); - return dataSource; + protected String defaultJdbcUrl() { + return "jdbc:mysql://localhost/high_performance_java_persistence?useSSL=false"; + } + + protected DataSource newDataSource() { + try { + MysqlDataSource dataSource = new MysqlDataSource(); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + dataSource.setRewriteBatchedStatements(rewriteBatchedStatements); + dataSource.setCachePrepStmts(cachePrepStmts); + dataSource.setUseServerPrepStmts(useServerPrepStmts); + + return dataSource; + } catch (SQLException e) { + throw new IllegalStateException("The DataSource could not be instantiated!"); + } } @Override @@ -102,22 +107,19 @@ public Class dataSourceClassName() { public Properties dataSourceProperties() { Properties properties = new Properties(); properties.setProperty("url", url()); + properties.setProperty("user", username()); + properties.setProperty("password", password()); return properties; } - @Override - public String url() { - return "jdbc:mysql://localhost/high_performance_java_persistence?user=mysql&password=admin"; - } - @Override public String username() { - return null; + return "mysql"; } @Override public String password() { - return null; + return "admin"; } @Override @@ -128,12 +130,12 @@ public Database database() { @Override public String toString() { return "MySQLDataSourceProvider{" + - "rewriteBatchedStatements=" + rewriteBatchedStatements + - ", cachePrepStmts=" + cachePrepStmts + - ", useServerPrepStmts=" + useServerPrepStmts + - ", useTimezone=" + useTimezone + - ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + - ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + - '}'; + "rewriteBatchedStatements=" + rewriteBatchedStatements + + ", cachePrepStmts=" + cachePrepStmts + + ", useServerPrepStmts=" + useServerPrepStmts + + ", useTimezone=" + useTimezone + + ", useJDBCCompliantTimezoneShift=" + useJDBCCompliantTimezoneShift + + ", useLegacyDatetimeCode=" + useLegacyDatetimeCode + + '}'; } } diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java index ec5d67c11..c6cabf7f9 100644 --- a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/OracleDataSourceProvider.java @@ -1,9 +1,10 @@ package com.vladmihalcea.hibernate.util.providers; -import com.vladmihalcea.hibernate.util.ReflectionUtils; +import oracle.jdbc.pool.OracleDataSource; import org.hibernate.dialect.OracleDialect; import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl; import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -11,20 +12,31 @@ /** * @author Vlad Mihalcea */ -public class OracleDataSourceProvider implements DataSourceProvider { +public class OracleDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return FastOracleDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:oracle:thin:@localhost:1521/xe"; + } + + @Override + public DataSource newDataSource() { try { - DataSource dataSource = ReflectionUtils.newInstance("oracle.jdbc.pool.OracleDataSource"); - ReflectionUtils.invokeSetter(dataSource, "databaseName", "high_performance_java_persistence"); - ReflectionUtils.invokeSetter(dataSource, "URL", url()); - ReflectionUtils.invokeSetter(dataSource, "user", "oracle"); - ReflectionUtils.invokeSetter(dataSource, "password", "admin"); + OracleDataSource dataSource = new OracleDataSource(); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setDatabaseName("high_performance_java_persistence"); + } else { + dataSource.setDatabaseName(container.getDatabaseName()); + } + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); return dataSource; } catch (Exception e) { throw new IllegalStateException(e); @@ -33,7 +45,7 @@ public DataSource dataSource() { @Override public Class dataSourceClassName() { - return ReflectionUtils.getClass("oracle.jdbc.pool.OracleDataSource"); + return OracleDataSource.class; } @Override @@ -46,11 +58,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:oracle:thin:@localhost:1521/xe"; - } - @Override public String username() { return "oracle"; diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java index f5585009c..9298f7cd3 100644 --- a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/PostgreSQLDataSourceProvider.java @@ -1,6 +1,5 @@ package com.vladmihalcea.hibernate.util.providers; -import org.hibernate.dialect.PostgreSQL95Dialect; import org.hibernate.dialect.PostgreSQLDialect; import org.postgresql.ds.PGSimpleDataSource; @@ -10,7 +9,7 @@ /** * @author Vlad Mihalcea */ -public class PostgreSQLDataSourceProvider implements DataSourceProvider { +public class PostgreSQLDataSourceProvider extends AbstractContainerDataSourceProvider { @Override public String hibernateDialect() { @@ -18,12 +17,16 @@ public String hibernateDialect() { } @Override - public DataSource dataSource() { + protected String defaultJdbcUrl() { + return "jdbc:postgresql://localhost/high_performance_java_persistence"; + } + + protected DataSource newDataSource() { PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setDatabaseName("high_performance_java_persistence"); - dataSource.setServerName("localhost"); - dataSource.setUser("postgres"); - dataSource.setPassword("admin"); + dataSource.setURL(url()); + dataSource.setUser(username()); + dataSource.setPassword(password()); + return dataSource; } @@ -42,11 +45,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return null; - } - @Override public String username() { return "postgres"; diff --git a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java index 58ff79c17..9113bd6f1 100644 --- a/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java +++ b/hibernate-types-60/src/test/java/com/vladmihalcea/hibernate/util/providers/SQLServerDataSourceProvider.java @@ -2,6 +2,7 @@ import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import org.hibernate.dialect.SQLServerDialect; +import org.testcontainers.containers.JdbcDatabaseContainer; import javax.sql.DataSource; import java.util.Properties; @@ -9,21 +10,30 @@ /** * @author Vlad Mihalcea */ -public class SQLServerDataSourceProvider implements DataSourceProvider { +public class SQLServerDataSourceProvider extends AbstractContainerDataSourceProvider { + @Override public String hibernateDialect() { return SQLServerDialect.class.getName(); } @Override - public DataSource dataSource() { + public String defaultJdbcUrl() { + return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; + } + + @Override + public DataSource newDataSource() { SQLServerDataSource dataSource = new SQLServerDataSource(); - dataSource.setURL( - "jdbc:sqlserver://localhost;instance=SQLEXPRESS;" + - "databaseName=high_performance_java_persistence;" - ); - dataSource.setUser("sa"); - dataSource.setPassword("adm1n"); + dataSource.setURL(url()); + JdbcDatabaseContainer container = database().getContainer(); + if(container == null) { + dataSource.setUser(username()); + dataSource.setPassword(password()); + } else { + dataSource.setUser(container.getUsername()); + dataSource.setPassword(container.getPassword()); + } return dataSource; } @@ -39,11 +49,6 @@ public Properties dataSourceProperties() { return properties; } - @Override - public String url() { - return "jdbc:sqlserver://localhost;instance=SQLEXPRESS;databaseName=high_performance_java_persistence;user=sa;password=adm1n"; - } - @Override public String username() { return "sa"; diff --git a/pom.xml b/pom.xml index 8eac3b08f..736aaa374 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,18 @@ hibernate-types-4 + + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + + + + @@ -127,6 +139,32 @@ test + + + + org.testcontainers + mysql + test + + + + org.testcontainers + postgresql + test + + + + org.testcontainers + oracle-xe + test + + + + org.testcontainers + mssqlserver + test + + @@ -154,7 +192,7 @@ - ${jdk.version} + ${jdk-test.version} @@ -166,6 +204,8 @@ ${jdk.version} ${jdk.version} + ${jdk-test.version} + ${jdk-test.version} true true @@ -175,7 +215,6 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - ${jdk8}/bin/java **/*JvmForkTest.java @@ -305,7 +344,6 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - ${jdk8}/bin/java false false @@ -328,7 +366,7 @@ 6 - ${env.JAVA_HOME_8} + 8 DEBUG @@ -356,6 +394,7 @@ 1.8.5 1.6 + 1.17.3 2.2.8 1.4.200 5.1.47