Skip to content

Commit

Permalink
Merge pull request quarkusio#40675 from yrodiere/orm-6.5.2-3.11
Browse files Browse the repository at this point in the history
[3.11] Backport to 3.11: Upgrade to Hibernate ORM 6.5.2 and configure Hibernate ORM/Reactive with database product names instead of dialect names for core dialects
  • Loading branch information
gsmet authored May 21, 2024
2 parents 090f819 + 3782329 commit 1b42a51
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 82 deletions.
4 changes: 2 additions & 2 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@
bytebuddy.version (just below), hibernate-orm.version-for-documentation (in docs/pom.xml)
and both hibernate-orm.version and antlr.version in build-parent/pom.xml
WARNING again for diffs that don't provide enough context: when updating, see above -->
<hibernate-orm.version>6.5.0.Final</hibernate-orm.version>
<bytebuddy.version>1.14.12</bytebuddy.version> <!-- Version controlled by Hibernate ORM's needs -->
<hibernate-orm.version>6.5.2.Final</hibernate-orm.version>
<bytebuddy.version>1.14.15</bytebuddy.version> <!-- Version controlled by Hibernate ORM's needs -->
<hibernate-commons-annotations.version>6.0.6.Final</hibernate-commons-annotations.version> <!-- version controlled by Hibernate ORM -->
<hibernate-reactive.version>2.3.0.Final</hibernate-reactive.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.hibernate.orm.deployment.spi;

import java.util.Optional;
import java.util.Set;

import io.quarkus.builder.item.MultiBuildItem;

Expand All @@ -9,15 +10,74 @@
*/
public final class DatabaseKindDialectBuildItem extends MultiBuildItem {
private final String dbKind;
private final String dialect;
private final Optional<String> databaseProductName;
private final Optional<String> dialect;
private final Set<String> matchingDialects;
private final Optional<String> defaultDatabaseProductVersion;

/**
* @param dbKind The DB Kind set through {@code quarkus.datasource.db-kind}
* @param databaseProductName The corresponding database-product-name to set in Hibernate ORM.
* See {@code org.hibernate.dialect.Database} for information on how this name is resolved to a dialect.
* @param dialects The corresponding dialects in Hibernate ORM,
* to detect the dbKind when using database multi-tenancy.
*/
public static DatabaseKindDialectBuildItem forCoreDialect(String dbKind, String databaseProductName,
Set<String> dialects) {
return new DatabaseKindDialectBuildItem(dbKind, Optional.empty(), Optional.of(databaseProductName),
dialects, Optional.empty());
}

/**
* @param dbKind The DB Kind set through {@code quarkus.datasource.db-kind}
* @param databaseProductName The corresponding database-product-name to set in Hibernate ORM.
* See {@code org.hibernate.dialect.Database} for information on how this name is resolved to a dialect.
* @param dialects The corresponding dialects in Hibernate ORM,
* to detect the dbKind when using database multi-tenancy.
* @param defaultDatabaseProductVersion The default database-product-version to set in Hibernate ORM.
* This is useful when the default version of the dialect in Hibernate ORM
* is lower than what we expect in Quarkus.
*/
public static DatabaseKindDialectBuildItem forCoreDialect(String dbKind, String databaseProductName,
Set<String> dialects, String defaultDatabaseProductVersion) {
return new DatabaseKindDialectBuildItem(dbKind, Optional.empty(), Optional.of(databaseProductName),
dialects, Optional.of(defaultDatabaseProductVersion));
}

/**
* @param dbKind The DB Kind set through {@code quarkus.datasource.db-kind}
* @param dialect The corresponding dialect to set in Hibernate ORM.
* See {@code org.hibernate.dialect.Database} for information on how this name is resolved to a dialect.
*/
public static DatabaseKindDialectBuildItem forThirdPartyDialect(String dbKind, String dialect) {
return new DatabaseKindDialectBuildItem(dbKind, Optional.of(dialect), Optional.empty(), Set.of(dialect),
Optional.empty());
}

/**
* @param dbKind The DB Kind set through {@code quarkus.datasource.db-kind}
* @param dialect The corresponding dialect to set in Hibernate ORM.
* See {@code org.hibernate.dialect.Database} for information on how this name is resolved to a dialect.
* @param defaultDatabaseProductVersion The default database-product-version to set in Hibernate ORM.
* This is useful when the default version of the dialect in Hibernate ORM
* is lower than what we expect in Quarkus.
*/
public static DatabaseKindDialectBuildItem forThirdPartyDialect(String dbKind, String dialect,
String defaultDatabaseProductVersion) {
return new DatabaseKindDialectBuildItem(dbKind, Optional.of(dialect), Optional.empty(),
Set.of(dialect), Optional.of(defaultDatabaseProductVersion));
}

/**
* @param dbKind The DB Kind set through {@code quarkus.datasource.db-kind}
* @param dialect The corresponding dialect to set in Hibernate ORM.
* @deprecated Use {@link #forCoreDialect(String, String, Set)}(different arguments!)
* for core Hibernate ORM dialects to avoid warnings on startup,
* or {@link #forThirdPartyDialect(String, String)} for community or third-party dialects.
*/
@Deprecated
public DatabaseKindDialectBuildItem(String dbKind, String dialect) {
this(dbKind, dialect, Optional.empty());
this(dbKind, Optional.of(dialect), Optional.empty(), Set.of(dialect), Optional.empty());
}

/**
Expand All @@ -27,15 +87,22 @@ public DatabaseKindDialectBuildItem(String dbKind, String dialect) {
* @param defaultDatabaseProductVersion The default database-product-version to set in Hibernate ORM.
* This is useful when the default version of the dialect in Hibernate ORM
* is lower than what we expect in Quarkus.
* @deprecated Use {@link #forCoreDialect(String, String, Set, String)}(different arguments!)
* for core Hibernate ORM dialects to avoid warnings on startup,
* or {@link #forThirdPartyDialect(String, String, String)} for community or third-party dialects.
*/
@Deprecated
public DatabaseKindDialectBuildItem(String dbKind, String dialect, String defaultDatabaseProductVersion) {
this(dbKind, dialect, Optional.of(defaultDatabaseProductVersion));
this(dbKind, Optional.of(dialect), Optional.empty(), Set.of(dialect), Optional.of(defaultDatabaseProductVersion));
}

private DatabaseKindDialectBuildItem(String dbKind, String dialect,
private DatabaseKindDialectBuildItem(String dbKind, Optional<String> dialect,
Optional<String> databaseProductName, Set<String> matchingDialects,
Optional<String> defaultDatabaseProductVersion) {
this.dbKind = dbKind;
this.dialect = dialect;
this.matchingDialects = matchingDialects;
this.databaseProductName = databaseProductName;
this.defaultDatabaseProductVersion = defaultDatabaseProductVersion;
}

Expand All @@ -44,9 +111,21 @@ public String getDbKind() {
}

public String getDialect() {
return dialect.get();
}

public Optional<String> getDialectOptional() {
return dialect;
}

public Set<String> getMatchingDialects() {
return matchingDialects;
}

public Optional<String> getDatabaseProductName() {
return databaseProductName;
}

public Optional<String> getDefaultDatabaseProductVersion() {
return defaultDatabaseProductVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ void setupLogFilters(BuildProducer<LogCleanupFilterBuildItem> filters) {
// Silence incubating settings warnings as we will use some for compatibility
filters.produce(new LogCleanupFilterBuildItem("org.hibernate.orm.incubating",
"HHH90006001"));
// https://hibernate.atlassian.net/browse/HHH-16546
filters.produce(new LogCleanupFilterBuildItem("org.hibernate.tuple.entity.EntityMetamodel", "HHH000157"));

//This "deprecation" warning isn't practical for the specific Quarkus needs, as it reminds users they don't need
//to set the 'hibernate.dialect' property, however it's being set by Quarkus buildsteps so they can't avoid it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,24 +162,27 @@ public final class HibernateOrmProcessor {
@BuildStep
void registerHibernateOrmMetadataForCoreDialects(
BuildProducer<DatabaseKindDialectBuildItem> producer) {
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.DB2,
"org.hibernate.dialect.DB2Dialect"));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.DERBY,
"org.hibernate.dialect.DerbyDialect"));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.H2,
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.DB2, "DB2",
Set.of("org.hibernate.dialect.DB2Dialect")));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.DERBY, "Apache Derby",
Set.of("org.hibernate.dialect.DerbyDialect")));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.H2, "H2",
Set.of("org.hibernate.dialect.H2Dialect"),
// Using our own default version is extra important for H2
// See https://github.com/quarkusio/quarkus/issues/1886
"org.hibernate.dialect.H2Dialect", DialectVersions.Defaults.H2));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.MARIADB,
"org.hibernate.dialect.MariaDBDialect", DialectVersions.Defaults.MARIADB));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.MSSQL,
"org.hibernate.dialect.SQLServerDialect", DialectVersions.Defaults.MSSQL));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.MYSQL,
"org.hibernate.dialect.MySQLDialect"));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.ORACLE,
"org.hibernate.dialect.OracleDialect"));
producer.produce(new DatabaseKindDialectBuildItem(DatabaseKind.POSTGRESQL,
"org.hibernate.dialect.PostgreSQLDialect"));
DialectVersions.Defaults.H2));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.MARIADB, "MariaDB",
Set.of("org.hibernate.dialect.MariaDBDialect"),
DialectVersions.Defaults.MARIADB));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.MSSQL, "Microsoft SQL Server",
Set.of("org.hibernate.dialect.SQLServerDialect"),
DialectVersions.Defaults.MSSQL));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.MYSQL, "MySQL",
Set.of("org.hibernate.dialect.MySQLDialect")));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.ORACLE, "Oracle",
Set.of("org.hibernate.dialect.OracleDialect")));
producer.produce(DatabaseKindDialectBuildItem.forCoreDialect(DatabaseKind.POSTGRESQL, "PostgreSQL",
Set.of("org.hibernate.dialect.PostgreSQLDialect")));
}

@BuildStep
Expand Down Expand Up @@ -1107,23 +1110,26 @@ private static void collectDialectConfig(String persistenceUnitName,
}

Optional<String> dialect = explicitDialect;
Optional<String> dbProductName = Optional.empty();
Optional<String> dbProductVersion = explicitDbMinVersion;
if (dbKind.isPresent() || explicitDialect.isPresent()) {
for (DatabaseKindDialectBuildItem item : dbKindMetadataBuildItems) {
if (dbKind.isPresent() && DatabaseKind.is(dbKind.get(), item.getDbKind())
// Set the default version based on the dialect when we don't have a datasource
// (i.e. for database multi-tenancy)
|| explicitDialect.isPresent() && explicitDialect.get().equals(item.getDialect())) {
if (explicitDialect.isEmpty()) {
dialect = Optional.of(item.getDialect());
|| explicitDialect.isPresent() && item.getMatchingDialects().contains(explicitDialect.get())) {
dbProductName = item.getDatabaseProductName();
if (dbProductName.isEmpty() && explicitDialect.isEmpty()) {
// Use dialects only as a last resort, prefer product name or explicitly user-provided dialect
dialect = item.getDialectOptional();
}
if (explicitDbMinVersion.isEmpty()) {
dbProductVersion = item.getDefaultDatabaseProductVersion();
}
break;
}
}
if (dialect.isEmpty()) {
if (dialect.isEmpty() && dbProductName.isEmpty()) {
throw new ConfigurationException(
"The Hibernate ORM extension could not guess the dialect from the database kind '" + dbKind.get()
+ "'. Add an explicit '"
Expand All @@ -1134,6 +1140,8 @@ private static void collectDialectConfig(String persistenceUnitName,

if (dialect.isPresent()) {
puPropertiesCollector.accept(AvailableSettings.DIALECT, dialect.get());
} else if (dbProductName.isPresent()) {
puPropertiesCollector.accept(AvailableSettings.JAKARTA_HBM2DDL_DB_NAME, dbProductName.get());
} else {
// We only get here with the database multi-tenancy strategy; see the initial check, up top.
assert multiTenancyStrategy == MultiTenancyStrategy.DATABASE;
Expand All @@ -1148,7 +1156,7 @@ private static void collectDialectConfig(String persistenceUnitName,

if (persistenceUnitConfig.dialect().storageEngine().isPresent()) {
// Only actually set the storage engines if MySQL or MariaDB
if (isMySQLOrMariaDB(dialect.get())) {
if (isMySQLOrMariaDB(dbKind, dialect)) {
// The storage engine has to be set as a system property.
// We record it so that we can later run checks (because we can only set a single value)
storageEngineCollector.add(persistenceUnitConfig.dialect().storageEngine().get());
Expand Down Expand Up @@ -1609,9 +1617,15 @@ private static Class[] toArray(final Set<Class<?>> interfaces) {
return interfaces.toArray(new Class[interfaces.size()]);
}

private static boolean isMySQLOrMariaDB(String dialect) {
String lowercaseDialect = dialect.toLowerCase(Locale.ROOT);
return lowercaseDialect.contains("mysql") || lowercaseDialect.contains("mariadb");
private static boolean isMySQLOrMariaDB(Optional<String> dbKind, Optional<String> dialect) {
if (dbKind.isPresent() && (DatabaseKind.isMySQL(dbKind.get()) || DatabaseKind.isMariaDB(dbKind.get()))) {
return true;
}
if (dialect.isPresent()) {
String lowercaseDialect = dialect.get().toLowerCase(Locale.ROOT);
return lowercaseDialect.contains("mysql") || lowercaseDialect.contains("mariadb");
}
return false;
}

private static final class ProxyCache {
Expand Down

This file was deleted.

Loading

0 comments on commit 1b42a51

Please sign in to comment.