Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Untranslated Hibernate exception [SPR-10815] #15441

Closed
spring-projects-issues opened this issue Aug 7, 2013 · 4 comments
Closed

Untranslated Hibernate exception [SPR-10815] #15441

spring-projects-issues opened this issue Aug 7, 2013 · 4 comments

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Aug 7, 2013

Archie Cobbs opened SPR-10815 and commented

The HibernateJpaDialect failed to translate the following exception into a TransientDataAccessException as it should have:

Caused by: javax.persistence.PessimisticLockException: could not obtain pessimistic lock
        at org.hibernate.ejb.AbstractEntityManagerImpl.wrapLockException(AbstractEntityManagerImpl.java:1439)
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1324)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:828)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:790)
        at sun.reflect.GeneratedMethodAccessor246.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
        at com.sun.proxy.$Proxy58.find(Unknown Source)
        ... 30 more
Caused by: org.hibernate.dialect.lock.PessimisticEntityLockException: could not obtain pessimistic lock
        at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:114)
        at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractEntityPersister.java:1896)
        at org.hibernate.event.internal.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:99)
        at org.hibernate.event.internal.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:512)
        at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:404)
        at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204)
        at org.hibernate.event.internal.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java:370)
        at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
        at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1079)
        at org.hibernate.internal.SessionImpl.access$2200(SessionImpl.java:172)
        at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2418)
        at org.hibernate.internal.SessionImpl.get(SessionImpl.java:1034)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:801)
        ... 36 more
Caused by: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
        at org.hibernate.dialect.MySQLDialect$1.convert(MySQLDialect.java:392)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
        at com.sun.proxy.$Proxy95.executeQuery(Unknown Source)
        at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:87)
        ... 48 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.Util.getInstance(Util.java:386)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1066)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
        at com.jolbox.bonecp.PreparedStatementHandle.executeQuery(PreparedStatementHandle.java:172)
        at sun.reflect.GeneratedMethodAccessor192.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
        ... 51 more

Is there a missing check for PessimisticEntityLockException?

Hibernate version is 4.1.6.Final.


Affects: 3.2.2

Issue Links:

  • #16293 Lock error is not translated to PessimisticLockingFailureException or subclass when using JPA (Hibernate)
@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 11, 2013

Archie Cobbs commented

Here's another variant:

org.springframework.orm.jpa.JpaSystemException: could not obtain pessimistic lock; nested exception is javax.persistence.PessimisticLockException: could not obtain pessimistic lock
        at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:321)
        at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:33)
        at ... elided ... 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
Caused by: javax.persistence.PessimisticLockException: could not obtain pessimistic lock
        at org.hibernate.ejb.AbstractEntityManagerImpl.wrapLockException(AbstractEntityManagerImpl.java:1439)
        at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1324)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:828)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:790)
        at sun.reflect.GeneratedMethodAccessor268.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
        at com.sun.proxy.$Proxy58.find(Unknown Source)
        ... 30 more
Caused by: org.hibernate.dialect.lock.PessimisticEntityLockException: could not obtain pessimistic lock
        at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:114)
        at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractEntityPersister.java:1896)
        at org.hibernate.event.internal.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:99)
        at org.hibernate.event.internal.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:512)
        at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:404)
        at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204)
        at org.hibernate.event.internal.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java:370)
        at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
        at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1079)
        at org.hibernate.internal.SessionImpl.access$2200(SessionImpl.java:172)
        at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2418)
        at org.hibernate.internal.SessionImpl.get(SessionImpl.java:1034)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:801)
        ... 36 more
Caused by: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
        at org.hibernate.dialect.MySQLDialect$1.convert(MySQLDialect.java:392)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
        at com.sun.proxy.$Proxy95.executeQuery(Unknown Source)
        at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:87)
        ... 48 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.Util.getInstance(Util.java:386)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1066)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
        at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
        at com.jolbox.bonecp.PreparedStatementHandle.executeQuery(PreparedStatementHandle.java:172)
        at sun.reflect.GeneratedMethodAccessor144.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
        ... 51 more

It looks like EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible() handles OptimisticLockException but not PessimisticLockException for some reason.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 11, 2013

Archie Cobbs commented

I think the actual problem is that the underlying Hibernate exception is wrapped inside two JPA exceptions, and HibernateJpaDialect.translateExceptionIfPossible() only checks one level deep.

My current workaround is to subclass HibernateJpaDialect with:


    /**
     * Adds fix for SPR-10815.
     *
     * @see <a href="https://jira.springsource.org/browse/SPR-10815">SPR-10815</a>
     */
    @Override
    public DataAccessException translateExceptionIfPossible(RuntimeException ex) {

        // Handle case that Spring has already wrapped and hidden the real exception without recognizing it
        for (Throwable t = ex; t != null; t = t.getCause()) {
            if (t instanceof RuntimeException) {
                final DataAccessException e = super.translateExceptionIfPossible((RuntimeException)t);
                if (e != null && !(e instanceof UncategorizedDataAccessException))
                    return e;
            }
        }

        // Give up
        return super.translateExceptionIfPossible(ex);
    }

(Still testing this fix though).

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 20, 2013

Juergen Hoeller commented

This is a little bit involved, unfortunately, since the nesting of LockAcquisitionException that you're seeing is an effect in Hibernate 4 only - and our current HibernateJpaDialect treats Hibernate 3 and 4 the same, being compatible with Hibernate 3.3+ still. This would also be less of a problem if we explicitly handled JPA 2.0's PessimisticLockException, which we're not doing in Spring 3.x since we're still JPA 1.0 compatible there...

So as of Spring Framework 4.0, HibernateJpaDialect has its own handling of Hibernate exceptions, fully covering Hibernate 3.6 and 4.x's range and structure of exceptions. This also makes HibernateJpaDialect independent from the presence of the native Hibernate support packages, allowing for future separation into distinct jars. At the same time, I've updated the native orm.hibernate3 and orm.hibernate4 support packages to have analogous coverage of the latest exceptions in the respective Hibernate generation.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 20, 2013

Archie Cobbs commented

Thanks for taking the time to analyze this and working to fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants