diff --git a/gradle/databases.gradle b/gradle/databases.gradle index 5bbefedcfe..8b38b82164 100644 --- a/gradle/databases.gradle +++ b/gradle/databases.gradle @@ -59,7 +59,8 @@ ext { 'jdbc.url' : 'jdbc:mysql://127.0.0.1/hibernate_orm_test' ], mariadb : [ - 'db.dialect' : 'org.hibernate.dialect.MariaDB102Dialect', + 'db.dialect' : '', +// 'db.dialect' : 'org.hibernate.dialect.MariaDB102Dialect', 'jdbc.driver': 'org.mariadb.jdbc.Driver', 'jdbc.user' : 'hibernate_orm_test', 'jdbc.pass' : 'hibernate_orm_test', diff --git a/gradle/java-module.gradle b/gradle/java-module.gradle index 9ef1908242..ce4ca056f7 100644 --- a/gradle/java-module.gradle +++ b/gradle/java-module.gradle @@ -207,6 +207,7 @@ tasks.withType( Test.class ).all { task -> } processTestResources { + inputs.property( "db", db ) doLast { copy { from( sourceSets.test.java.srcDirs ) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java index ce579baddc..9c0abaca38 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDB103Dialect.java @@ -7,11 +7,12 @@ package org.hibernate.dialect; +import org.hibernate.LockOptions; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.type.StandardBasicTypes; /** - * An SQL dialect for MariaDB 10.3 and later, provides sequence support. + * An SQL dialect for MariaDB 10.3 and later, provides sequence support, lock-timeouts, etc. * * @author Philippe Marschall */ @@ -58,4 +59,27 @@ public class MariaDB103Dialect extends MariaDB102Dialect { return "select table_name from information_schema.TABLES where table_type='SEQUENCE'"; } + @Override + public String getWriteLockString(int timeout) { + if ( timeout == LockOptions.NO_WAIT ) { + return getForUpdateNowaitString(); + } + + if ( timeout > 0 ) { + return getForUpdateString() + " wait " + timeout; + } + + return getForUpdateString(); + } + + @Override + public String getForUpdateNowaitString() { + return getForUpdateString() + " nowait"; + } + + @Override + public String getForUpdateNowaitString(String aliases) { + return getForUpdateString( aliases ) + " nowait"; + } + } 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 45aa1852fd..b7ee0fdf56 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -13,6 +13,7 @@ import java.sql.Types; import org.hibernate.JDBCException; import org.hibernate.NullPrecedence; +import org.hibernate.PessimisticLockException; import org.hibernate.boot.TempTableDdlTransactionHandling; import org.hibernate.cfg.Environment; import org.hibernate.dialect.function.NoArgSQLFunction; @@ -525,6 +526,16 @@ public class MySQLDialect extends Dialect { return new SQLExceptionConversionDelegate() { @Override public JDBCException convert(SQLException sqlException, String message, String sql) { + switch ( sqlException.getErrorCode() ) { + case 1205: { + return new PessimisticLockException( message, sqlException, sql ); + } + case 1207: + case 1206: { + return new LockAcquisitionException( message, sqlException, sql ); + } + } + final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException ); if ( "41000".equals( sqlState ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/ExceptionConverterImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/ExceptionConverterImpl.java index 1d373f3e96..a5b3401663 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/ExceptionConverterImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/ExceptionConverterImpl.java @@ -8,7 +8,6 @@ package org.hibernate.internal; import java.io.Serializable; import java.sql.SQLException; - import javax.persistence.EntityExistsException; import javax.persistence.EntityNotFoundException; import javax.persistence.LockTimeoutException; @@ -34,6 +33,7 @@ import org.hibernate.dialect.lock.OptimisticEntityLockException; import org.hibernate.dialect.lock.PessimisticEntityLockException; import org.hibernate.engine.spi.ExceptionConverter; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.exception.LockAcquisitionException; import org.hibernate.loader.MultipleBagFetchException; /** @@ -89,12 +89,12 @@ public class ExceptionConverterImpl implements ExceptionConverter { handlePersistenceException( converted ); return converted; } - else if ( cause instanceof LockingStrategyException ) { + else if ( cause instanceof LockAcquisitionException ) { final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions ); handlePersistenceException( converted ); return converted; } - else if ( cause instanceof org.hibernate.exception.LockTimeoutException ) { + else if ( cause instanceof LockingStrategyException ) { final PersistenceException converted = wrapLockException( (HibernateException) cause, lockOptions ); handlePersistenceException( converted ); return converted; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ForUpdateFragment.java b/hibernate-core/src/main/java/org/hibernate/sql/ForUpdateFragment.java index 6d7030cbe6..df3f4554aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ForUpdateFragment.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ForUpdateFragment.java @@ -69,11 +69,11 @@ public class ForUpdateFragment { } } - if ( upgradeType == LockMode.UPGRADE_NOWAIT ) { + if ( upgradeType == LockMode.UPGRADE_NOWAIT || lockOptions.getTimeOut() == LockOptions.NO_WAIT ) { setNowaitEnabled( true ); } - if ( upgradeType == LockMode.UPGRADE_SKIPLOCKED ) { + if ( upgradeType == LockMode.UPGRADE_SKIPLOCKED || lockOptions.getTimeOut() == LockOptions.SKIP_LOCKED ) { setSkipLockedEnabled( true ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/jpa/lock/LockExceptionTests.java b/hibernate-core/src/test/java/org/hibernate/test/jpa/lock/LockExceptionTests.java index 01020dec39..db126b89b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/jpa/lock/LockExceptionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/test/jpa/lock/LockExceptionTests.java @@ -14,11 +14,8 @@ import javax.persistence.PessimisticLockException; import org.hibernate.LockOptions; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Configuration; -import org.hibernate.dialect.MariaDBDialect; import org.hibernate.dialect.SQLServerDialect; -import org.hibernate.testing.SkipForDialect; -import org.hibernate.testing.SkipForDialects; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.jdbc.SQLServerSnapshotIsolationConnectionProvider; import org.hibernate.testing.transaction.TransactionUtil2; @@ -31,9 +28,6 @@ import static org.junit.Assert.fail; /** * @author Steve Ebersole */ -@SkipForDialects( - @SkipForDialect( value = MariaDBDialect.class, jiraKey = "HHH-8786", comment = "https://hibernate.atlassian.net/browse/HHH-8786") -) public class LockExceptionTests extends AbstractJPATest { @Override public void configure(Configuration cfg) { @@ -77,6 +71,9 @@ public class LockExceptionTests extends AbstractJPATest { } ); } + catch (Exception e) { + e.printStackTrace(); + } finally { inTransaction( session -> session.createQuery( "delete Item" ).executeUpdate()