Author: smarlow(a)redhat.com
Date: 2010-03-05 17:22:05 -0500 (Fri, 05 Mar 2010)
New Revision: 18931
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java
Log:
HHH-4972 javax.persistence.query.timeout and javax.persistence.lock.timeout can be passed
when creating an EMF
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-03-05
18:17:36 UTC (rev 18930)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-03-05
22:22:05 UTC (rev 18931)
@@ -118,6 +118,7 @@
entityManagerSpecificProperties.add( AvailableSettings.FLUSH_MODE );
entityManagerSpecificProperties.add( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE );
entityManagerSpecificProperties.add( AvailableSettings.SHARED_CACHE_STORE_MODE );
+ entityManagerSpecificProperties.add( QueryHints.SPEC_HINT_TIMEOUT );
}
private EntityManagerFactoryImpl entityManagerFactory;
@@ -168,6 +169,17 @@
);
}
+ private Query applyProperties(Query query) {
+ if ( lockOptions.getLockMode() != LockMode.NONE ) {
+ query.setLockMode( getLockMode(lockOptions.getLockMode()));
+ }
+ Object queryTimeout;
+ if ( (queryTimeout = getProperties().get(QueryHints.SPEC_HINT_TIMEOUT)) != null ) {
+ query.setHint ( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout );
+ }
+ return query;
+ }
+
private CacheRetrieveMode currentCacheRetrieveMode() {
return determineCacheRetrieveMode( properties );
}
@@ -248,7 +260,7 @@
public Query createQuery(String jpaqlString) {
try {
- return new QueryImpl<Object>( getSession().createQuery( jpaqlString ), this );
+ return applyProperties( new QueryImpl<Object>( getSession().createQuery(
jpaqlString ), this ) );
}
catch ( HibernateException he ) {
throw convert( he );
Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java 2010-03-05
18:17:36 UTC (rev 18930)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/TestCase.java 2010-03-05
22:22:05 UTC (rev 18931)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
@@ -134,6 +134,12 @@
return isolatedEm;
}
+ protected EntityManager createIsolatedEntityManager(Map props) {
+ EntityManager isolatedEm = factory.createEntityManager(props);
+ isolatedEms.add( isolatedEm );
+ return isolatedEm;
+ }
+
/**
* always reopen a new EM and clse the existing one
*/
Modified:
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java
===================================================================
---
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java 2010-03-05
18:17:36 UTC (rev 18930)
+++
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/test/lock/LockTest.java 2010-03-05
22:22:05 UTC (rev 18931)
@@ -601,7 +601,96 @@
}
}
+ public void testQueryTimeoutEMProps() throws Exception {
+ // TODO: replace dialect instanceof test with a Dialect.hasCapability
+ if ( ! (getDialect() instanceof Oracle10gDialect)) {
+ log.info("skipping testQueryTimeout");
+ return;
+ }
+ EntityManager em = getOrCreateEntityManager();
+ Map queryTimeoutProps = new HashMap();
+ queryTimeoutProps.put("javax.persistence.query.timeout", new Integer(500) );
// 1 sec timeout (should round up)
+ final EntityManager em2 = createIsolatedEntityManager(queryTimeoutProps);
+ Lock lock = new Lock();
+ Thread t = null;
+ FutureTask<Boolean> bgTask = null;
+ final CountDownLatch latch = new CountDownLatch(1);
+ try {
+ lock.setName( "testQueryTimeout" );
+ em.getTransaction().begin();
+ em.persist( lock );
+ em.getTransaction().commit();
+ em.clear();
+
+ em.getTransaction().begin();
+ lock = em.getReference( Lock.class, lock.getId() );
+ em.lock( lock, LockModeType.PESSIMISTIC_WRITE );
+ final Integer id = lock.getId();
+ lock.getName(); // force entity to be read
+ log.info("testQueryTimeout: got write lock");
+
+ bgTask = new FutureTask<Boolean>( new Callable() {
+ public Boolean call() {
+ try {
+ boolean timedOut = false; // true (success) if LockTimeoutException occurred
+ em2.getTransaction().begin();
+ log.info( "testQueryTimeout: (BG) about to read write-locked entity" );
+ // we should block on the following read
+ Lock lock2 = em2.getReference( Lock.class, id );
+ lock2.getName(); // force entity to be read
+ log.info( "testQueryTimeout: (BG) read write-locked entity" );
+ try {
+ // we should block on the following read
+ Query query = em2.createQuery(
+ "select L from Lock_ L where L.id < 10000 ");
+ query.setLockMode( LockModeType.PESSIMISTIC_READ );
+ List<Lock> resultList = query.getResultList();
+ String name = resultList.get(0).getName(); // force entity to be read
+ log.info( "testQueryTimeout: name read =" + name );
+ }
+ catch( QueryTimeoutException e) {
+ // success
+ log.info( "testQueryTimeout: (BG) got expected timeout exception" );
+ timedOut = true;
+ }
+ catch ( Throwable e) {
+ log.info( "testQueryTimeout: Expected LockTimeoutException but got unexpected
exception", e );
+ }
+ em2.getTransaction().commit();
+ return new Boolean( timedOut );
+ }
+ finally {
+ latch.countDown(); // signal that we finished
+ }
+ }
+ } );
+ t = new Thread(bgTask);
+ t.setDaemon( true );
+ t.setName( "testQueryTimeout (bg)" );
+ t.start();
+ boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on
success
+ assertTrue( "background test thread finished (lock timeout is broken)",
latchSet);
+ assertTrue( "background test thread timed out on lock attempt",
bgTask.get().booleanValue() );
+ em.getTransaction().commit();
+ }
+ finally {
+ if ( em.getTransaction().isActive() ) {
+ em.getTransaction().rollback();
+ }
+ if ( t != null) { // wait for background thread to finish before deleting entity
+ t.join();
+ }
+ em.getTransaction().begin();
+ lock = em.getReference( Lock.class, lock.getId() );
+ em.remove( lock );
+ em.getTransaction().commit();
+ em.close();
+ em2.close();
+ }
+ }
+
+
public Class[] getAnnotatedClasses() {
return new Class[]{
Lock.class,
Show replies by date