/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.jpa.test.lock; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import javax.persistence.LockModeType; import org.hibernate.Session; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider; import org.hibernate.testing.transaction.TransactionUtil; import org.hibernate.testing.util.ExceptionUtil; import org.junit.Before; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; /** * @author Andrea Boriero */ public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerFunctionalTestCase { private static final PreparedStatementSpyConnectionProvider CONNECTION_PROVIDER = new PreparedStatementSpyConnectionProvider(); private Integer lockId; @Override protected Map getConfig() { Map config = super.getConfig(); config.put( org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, CONNECTION_PROVIDER ); return config; } @Before public void setUp() { lockId = TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { Lock lock = new Lock(); lock.setName( "name" ); entityManager.persist( lock ); return lock.getId(); } ); } @Override public void releaseResources() { super.releaseResources(); CONNECTION_PROVIDER.stop(); } @Test(timeout = 1000 * 10) //10 seconds @TestForIssue(jiraKey = "HHH-11617") public void testStatementIsClosed() { TransactionUtil.doInJPA( this::entityManagerFactory, em1 -> { Map<String, Object> properties = new HashMap<>(); properties.put( org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT, 0L ); Lock lock2 = em1.find( Lock.class, lockId, LockModeType.PESSIMISTIC_WRITE, properties ); assertEquals( "lock mode should be PESSIMISTIC_WRITE ", LockModeType.PESSIMISTIC_WRITE, em1.getLockMode( lock2 ) ); TransactionUtil.doInJPA( this::entityManagerFactory, em2 -> { TransactionUtil.setJdbcTimeout( em2.unwrap( Session.class ) ); try { em2.find( Lock.class, lockId, LockModeType.PESSIMISTIC_WRITE, properties ); fail( "Exception should be thrown" ); } catch (Exception lte) { if( !ExceptionUtil.isSqlLockTimeout( lte )) { fail("Should have thrown a Lock timeout exception"); } } finally { try { for ( PreparedStatement statement : CONNECTION_PROVIDER.getPreparedStatements() ) { assertThat( "A SQL Statement was not closed : " + statement.toString(), statement.isClosed(), is( true ) ); } } catch (SQLException e) { fail( e.getMessage() ); } } } ); } ); } @Override public Class[] getAnnotatedClasses() { return new Class[] { Lock.class, UnversionedLock.class }; } }