diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/SchemaToolingSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/SchemaToolingSettings.java index b8becd4334ff..ffff3b0525d3 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/SchemaToolingSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/SchemaToolingSettings.java @@ -295,9 +295,10 @@ public interface SchemaToolingSettings { /** * Specifies the default storage engine for a relational database that supports - * multiple storage engines. This property must be set either as an {@link Environment} - * variable or JVM System Property, since the {@link org.hibernate.dialect.Dialect} is - * instantiated before Hibernate property resolution. + * multiple storage engines. + * + * This property can be set as an {@link Environment} variable, a JVM System Property + * or a configuration property. *
* For MySQL, the legal values are {@code innodb} (the default) and {@code myisam}.
*
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
index 3c64dec330f4..42d47073987d 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java
@@ -93,6 +93,7 @@
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;
+import java.util.Locale;
import java.util.TimeZone;
import static java.lang.Integer.parseInt;
@@ -146,7 +147,7 @@ public class MySQLDialect extends Dialect {
private static final DatabaseVersion MINIMUM_VERSION = DatabaseVersion.make( 8 );
- private final MySQLStorageEngine storageEngine = createStorageEngine();
+ private final MySQLStorageEngine storageEngine;
private final SizeStrategy sizeStrategy = new SizeStrategyImpl() {
@Override
@@ -207,7 +208,11 @@ public MySQLDialect(DatabaseVersion version, int bytesPerCharacter) {
}
public MySQLDialect(DatabaseVersion version, MySQLServerConfiguration serverConfiguration) {
- this( version, serverConfiguration.getBytesPerCharacter(), serverConfiguration.isNoBackslashEscapesEnabled() );
+ super( version );
+ maxVarcharLength = maxVarcharLength( getMySQLVersion(), serverConfiguration.getBytesPerCharacter() ); //conservative assumption
+ maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() );
+ noBackslashEscapesEnabled = serverConfiguration.isNoBackslashEscapesEnabled();
+ storageEngine = createStorageEngine( serverConfiguration.getConfiguredStorageEngine() );
}
public MySQLDialect(DatabaseVersion version, int bytesPerCharacter, boolean noBackslashEscapes) {
@@ -215,6 +220,7 @@ public MySQLDialect(DatabaseVersion version, int bytesPerCharacter, boolean noBa
maxVarcharLength = maxVarcharLength( getMySQLVersion(), bytesPerCharacter ); //conservative assumption
maxVarbinaryLength = maxVarbinaryLength( getMySQLVersion() );
noBackslashEscapesEnabled = noBackslashEscapes;
+ storageEngine = createStorageEngine( Environment.getProperties().getProperty( AvailableSettings.STORAGE_ENGINE ) );
}
public MySQLDialect(DialectResolutionInfo info) {
@@ -257,13 +263,10 @@ protected void initDefaultProperties() {
getDefaultProperties().setProperty( FetchSettings.MAX_FETCH_DEPTH, "2" );
}
- private MySQLStorageEngine createStorageEngine() {
- final String storageEngine =
- Environment.getProperties()
- .getProperty( AvailableSettings.STORAGE_ENGINE );
- return storageEngine == null
+ private MySQLStorageEngine createStorageEngine(String configuredStorageEngine) {
+ return configuredStorageEngine == null
? getDefaultMySQLStorageEngine()
- : switch ( storageEngine ) {
+ : switch ( configuredStorageEngine.toLowerCase(Locale.ROOT) ) {
case "innodb" -> InnoDBStorageEngine.INSTANCE;
case "myisam" -> MyISAMStorageEngine.INSTANCE;
default -> throw new UnsupportedOperationException(
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLServerConfiguration.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLServerConfiguration.java
index 362f7af9c668..bb8905e2488f 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLServerConfiguration.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLServerConfiguration.java
@@ -9,7 +9,9 @@
import java.sql.SQLException;
import org.hibernate.Internal;
+import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
+import org.hibernate.internal.util.config.ConfigurationHelper;
import static org.hibernate.cfg.DialectSpecificSettings.MYSQL_BYTES_PER_CHARACTER;
import static org.hibernate.cfg.DialectSpecificSettings.MYSQL_NO_BACKSLASH_ESCAPES;
@@ -26,10 +28,18 @@
public class MySQLServerConfiguration {
private final int bytesPerCharacter;
private final boolean noBackslashEscapesEnabled;
+ private final String storageEngine;
public MySQLServerConfiguration(int bytesPerCharacter, boolean noBackslashEscapesEnabled) {
this.bytesPerCharacter = bytesPerCharacter;
this.noBackslashEscapesEnabled = noBackslashEscapesEnabled;
+ this.storageEngine = null;
+ }
+
+ public MySQLServerConfiguration(int bytesPerCharacter, boolean noBackslashEscapesEnabled, String storageEngine) {
+ this.bytesPerCharacter = bytesPerCharacter;
+ this.noBackslashEscapesEnabled = noBackslashEscapesEnabled;
+ this.storageEngine = storageEngine;
}
public int getBytesPerCharacter() {
@@ -40,6 +50,10 @@ public boolean isNoBackslashEscapesEnabled() {
return noBackslashEscapesEnabled;
}
+ public String getConfiguredStorageEngine() {
+ return storageEngine;
+ }
+
static Integer getBytesPerCharacter(String characterSet) {
final int collationIndex = characterSet.indexOf( '_' );
// According to https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html
@@ -78,7 +92,11 @@ public static MySQLServerConfiguration fromDialectResolutionInfo(DialectResoluti
if ( noBackslashEscapes == null ) {
noBackslashEscapes = getBoolean( MYSQL_NO_BACKSLASH_ESCAPES, info.getConfigurationValues(), false );
}
- return new MySQLServerConfiguration( bytesPerCharacter, noBackslashEscapes );
+
+ return new MySQLServerConfiguration(
+ bytesPerCharacter,
+ noBackslashEscapes,
+ ConfigurationHelper.getString( AvailableSettings.STORAGE_ENGINE, info.getConfigurationValues() ) );
}
/**
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/unit/lockhint/MySQLStorageEngineTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/unit/lockhint/MySQLStorageEngineTest.java
index f1a3da96e901..12907d59f07f 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/unit/lockhint/MySQLStorageEngineTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/unit/lockhint/MySQLStorageEngineTest.java
@@ -4,26 +4,37 @@
*/
package org.hibernate.orm.test.dialect.unit.lockhint;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.DatabaseVersion;
+import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
-
-import org.hibernate.testing.junit4.BaseUnitTestCase;
+import org.hibernate.orm.test.dialect.resolver.TestingDialectResolutionInfo;
+import org.hibernate.testing.orm.junit.BaseUnitTest;
+import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import org.hibernate.testing.orm.junit.ServiceRegistry;
+import org.hibernate.testing.orm.junit.SessionFactory;
+import org.hibernate.testing.orm.junit.SessionFactoryScope;
+import org.hibernate.testing.orm.junit.Setting;
+import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
@RequiresDialect(MySQLDialect.class)
-public class MySQLStorageEngineTest extends BaseUnitTestCase {
+@BaseUnitTest
+public class MySQLStorageEngineTest {
@Test
public void testDefaultStorage() {
- assertEquals( " engine=InnoDB", new MySQLDialect().getTableTypeString() );
+ assertThat( new MySQLDialect().getTableTypeString() ).isEqualTo( " engine=InnoDB" );
}
@Test
@@ -31,10 +42,49 @@ public void testOverrideStorage() throws NoSuchFieldException, IllegalAccessExce
final Field globalPropertiesField = Environment.class.getDeclaredField( "GLOBAL_PROPERTIES" );
globalPropertiesField.setAccessible( true );
final Properties systemProperties = (Properties) globalPropertiesField.get( null );
- assertNotNull( systemProperties );
+ assertThat( systemProperties ).isNotNull();
+ final Object previousValue = systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, "myisam" );
+ try {
+ assertThat( new MySQLDialect().getTableTypeString() ).isEqualTo( " engine=MyISAM" );
+ }
+ finally {
+ if ( previousValue != null ) {
+ systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, previousValue.toString() );
+ }
+ else {
+ systemProperties.remove( AvailableSettings.STORAGE_ENGINE );
+ }
+ }
+ }
+
+ @Test
+ @SessionFactory
+ @ServiceRegistry(settings = {@Setting(name = AvailableSettings.STORAGE_ENGINE, value = "myisam")})
+ @DomainModel(annotatedClasses = {TestEntity.class})
+ public void testOverrideStorageWithConfigurationProperties(SessionFactoryScope scope) {
+ Dialect dialect = scope.getSessionFactory().getJdbcServices().getDialect();
+ assertThat( dialect.getTableTypeString() ).isEqualTo( " engine=MyISAM" );
+ }
+
+ @Test
+ public void testOverrideStorageEngineConfigurationPropertyHasPrecedenceOverSystemProperty()
+ throws Exception {
+ final Field globalPropertiesField = Environment.class.getDeclaredField( "GLOBAL_PROPERTIES" );
+ globalPropertiesField.setAccessible( true );
+ final Properties systemProperties = (Properties) globalPropertiesField.get( null );
+ assertThat( systemProperties ).isNotNull();
final Object previousValue = systemProperties.setProperty( AvailableSettings.STORAGE_ENGINE, "myisam" );
try {
- assertEquals( " engine=MyISAM", new MySQLDialect().getTableTypeString() );
+ final Map