HHH-6256 persistence.xml-specified javax.persistence.lock.timeout is ignored

HHH-6846 Support for Query.setHint(javax.persistence.lock.timeout)
This commit is contained in:
Strong Liu 2012-05-29 18:15:59 +08:00
parent 4266cd3585
commit ed266c593a
5 changed files with 69 additions and 21 deletions

View File

@ -61,23 +61,16 @@ public class LockModeTest extends BaseCoreFunctionalTestCase {
return new Class[] { A.class };
}
@Before
public void createData() {
@Override
public void prepareTest() throws Exception {
Session session = sessionFactory().openSession();
session.beginTransaction();
id = (Long) session.save( new A( "it" ) );
session.getTransaction().commit();
session.close();
}
@After
public void cleanupData() {
Session session = sessionFactory().openSession();
session.beginTransaction();
session.createQuery( "delete A" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
@Override
protected boolean isCleanupTestDataRequired(){return true;}
@Test
@SuppressWarnings( {"deprecation"})

View File

@ -158,11 +158,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
this.lockOptions = new LockOptions();
this.properties = new HashMap<String, Object>();
if ( properties != null ) {
for ( String key : entityManagerSpecificProperties ) {
if ( properties.containsKey( key ) ) {
this.properties.put( key, properties.get( key ) );
}
for ( String key : entityManagerSpecificProperties ) {
if ( entityManagerFactory.getProperties().containsKey( key ) ) {
this.properties.put( key, entityManagerFactory.getProperties().get( key ) );
}
if ( properties != null && properties.containsKey( key ) ) {
this.properties.put( key, properties.get( key ) );
}
}
}
@ -200,6 +201,10 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( (queryTimeout = getProperties().get(QueryHints.SPEC_HINT_TIMEOUT)) != null ) {
query.setHint ( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout );
}
Object lockTimeout;
if( (lockTimeout = getProperties().get( AvailableSettings.LOCK_TIMEOUT ))!=null){
query.setHint( AvailableSettings.LOCK_TIMEOUT, lockTimeout );
}
return query;
}

View File

@ -177,6 +177,8 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
protected abstract void applyTimeout(int timeout);
protected abstract void applyLockTimeout(int timeout);
protected abstract void applyComment(String comment);
protected abstract void applyFetchSize(int fetchSize);
@ -208,6 +210,10 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
int timeout = (int)Math.round(ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 );
applyTimeout( timeout );
}
else if ( AvailableSettings.LOCK_TIMEOUT.equals( hintName ) ) {
int timeout = (int)Math.round(ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 );
applyLockTimeout( timeout );
}
else if ( HINT_COMMENT.equals( hintName ) ) {
applyComment( (String) value );
}

View File

@ -50,6 +50,7 @@ import org.hibernate.QueryParameterException;
import org.hibernate.SQLQuery;
import org.hibernate.TypeMismatchException;
import org.hibernate.ejb.internal.EntityManagerMessageLogger;
import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.ejb.util.LockModeTypeHelper;
import org.hibernate.engine.query.spi.NamedParameterDescriptor;
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
@ -631,9 +632,22 @@ public class QueryImpl<X> extends org.hibernate.ejb.AbstractQueryImpl<X> impleme
( (org.hibernate.internal.QueryImpl) query ).getLockOptions().setLockMode(
LockModeTypeHelper.getLockMode( lockModeType )
);
if ( getHints()!=null && getHints().containsKey( AvailableSettings.LOCK_TIMEOUT ) ) {
// convert milliseconds to seconds
int timeout = (int) Math.round(
ConfigurationHelper.getInteger( getHints().get( AvailableSettings.LOCK_TIMEOUT ) )
.doubleValue() / 1000.0
);
applyTimeout( timeout );
}
return this;
}
@Override
protected void applyLockTimeout(int timeout) {
( (org.hibernate.internal.QueryImpl) query ).getLockOptions().setTimeOut( timeout );
}
@Override
public javax.persistence.LockModeType getLockMode() {
return jpaLockMode;

View File

@ -29,6 +29,7 @@ import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.SybaseASE15Dialect;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.internal.AbstractSessionImpl;
import org.hibernate.internal.QueryImpl;
import org.hibernate.testing.*;
@ -62,6 +63,35 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
assertEquals( 3, timeout );
}
@Override
protected void addConfigOptions(Map options) {
options.put( AvailableSettings.LOCK_TIMEOUT, "2000" );
}
@Test
@TestForIssue( jiraKey = "HHH-6256")
public void testTimeoutHint(){
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
boolean b= em.getProperties().containsKey( AvailableSettings.LOCK_TIMEOUT );
assertTrue( b );
int timeout = Integer.valueOf( em.getProperties().get( AvailableSettings.LOCK_TIMEOUT ).toString() );
assertEquals( 2000, timeout);
org.hibernate.ejb.QueryImpl q = (org.hibernate.ejb.QueryImpl) em.createQuery( "select u from UnversionedLock u" );
timeout = ((QueryImpl)q.getHibernateQuery()).getLockOptions().getTimeOut();
assertEquals( 2, timeout );
Query query = em.createQuery( "select u from UnversionedLock u" );
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
query.setHint( AvailableSettings.LOCK_TIMEOUT, 3000 );
q = (org.hibernate.ejb.QueryImpl)query;
timeout = ((QueryImpl)q.getHibernateQuery()).getLockOptions().getTimeOut();
assertEquals( 3, timeout );
em.getTransaction().rollback();
em.close();
}
@Test
public void testFindWithTimeoutHint() {
EntityManager em = getOrCreateEntityManager();
@ -493,7 +523,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
log.info( "testContendedPessimisticReadLockTimeout: (BG) read write-locked entity" );
Map<String, Object> props = new HashMap<String, Object>();
// timeout is in milliseconds
props.put( "javax.persistence.lock.timeout", 1000 );
props.put( "AvailableSettings.LOCK_TIMEOUT", 1000 );
try {
em2.lock( lock2, LockModeType.PESSIMISTIC_READ, props );
}
@ -587,7 +617,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
log.info( "testContendedPessimisticWriteLockTimeout: (BG) read write-locked entity" );
Map<String, Object> props = new HashMap<String, Object>();
// timeout is in milliseconds
props.put( "javax.persistence.lock.timeout", 1000 );
props.put( "AvailableSettings.LOCK_TIMEOUT", 1000 );
try {
em2.lock( lock2, LockModeType.PESSIMISTIC_WRITE, props );
}
@ -676,7 +706,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
log.info( "testContendedPessimisticWriteLockNoWait: (BG) read write-locked entity" );
Map<String, Object> props = new HashMap<String, Object>();
// timeout of zero means no wait (for lock)
props.put( "javax.persistence.lock.timeout", 0 );
props.put( "AvailableSettings.LOCK_TIMEOUT", 0 );
try {
em2.lock( lock2, LockModeType.PESSIMISTIC_WRITE, props );
}
@ -917,7 +947,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
EntityManager em = getOrCreateEntityManager();
Map<String, Object> TimeoutProps = new HashMap<String, Object>();
TimeoutProps.put( "javax.persistence.lock.timeout", 1000 ); // 1 second timeout
TimeoutProps.put( "AvailableSettings.LOCK_TIMEOUT", 1000 ); // 1 second timeout
final EntityManager em2 = createIsolatedEntityManager( TimeoutProps );
Lock lock = new Lock();
Thread t = null;
@ -949,7 +979,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Lock lock2 = em2.getReference( Lock.class, id );
lock2.getName(); // force entity to be read
log.info( "testLockTimeoutEMProps: (BG) read write-locked entity" );
// em2 already has javax.persistence.lock.timeout of 1 second applied
// em2 already has AvailableSettings.LOCK_TIMEOUT of 1 second applied
try {
em2.lock( lock2, LockModeType.PESSIMISTIC_WRITE );
}