diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java index aec6593eb..5982e03f7 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.java @@ -31,6 +31,7 @@ import org.apache.openjpa.jdbc.sql.SQLBuffer; import org.apache.openjpa.jdbc.sql.SQLExceptions; import org.apache.openjpa.jdbc.sql.SQLFactory; import org.apache.openjpa.jdbc.sql.Select; +import org.apache.openjpa.kernel.MixedLockLevels; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.VersionLockManager; @@ -140,7 +141,8 @@ public class PessimisticLockManager } catch (SQLException se) { LockException e = new LockException(sm.getPersistenceCapable(), timeout, level); e.setCause(se); - e.setFatal(dict.isFatalException(StoreException.LOCK, se)); + e.setFatal(dict.isFatalException(StoreException.LOCK, se) + || level >= MixedLockLevels.LOCK_PESSIMISTIC_READ); throw e; } finally { if (stmnt != null) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java index d06501afc..06bfdd8bb 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java @@ -129,8 +129,7 @@ public class SQLExceptions { /** * Convert the specified exception into a {@link StoreException}. */ - public static OpenJPAException getStore(String msg, SQLException se, - Object failed, DBDictionary dict, int level) { + public static OpenJPAException getStore(String msg, SQLException se, Object failed, DBDictionary dict, int level) { if (msg == null) msg = se.getClass().getName(); SQLException[] ses = getSQLExceptions(se); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java index afcb31e2f..039b965df 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java @@ -326,7 +326,7 @@ public class DataCacheStoreManager boolean fromDatabase; DataCache cache = _mgr.selectCache(sm); DataCachePCData data = null; - boolean updateCache = _ctx.getFetchConfiguration().getCacheStoreMode() != DataCacheStoreMode.BYPASS + boolean updateCache = _ctx.getFetchConfiguration().getCacheRetrieveMode() != DataCacheRetrieveMode.BYPASS && _ctx.getPopulateDataCache(); if (cache == null || sm.isEmbedded() || _ctx.getFetchConfiguration().getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java index d237e53ec..82f039456 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java @@ -30,6 +30,8 @@ import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; +import org.apache.openjpa.util.Exceptions; +import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.RuntimeExceptionTranslator; /////////////////////////////////////////////////////////////// @@ -103,6 +105,25 @@ public class DelegatingBroker protected RuntimeException translate(RuntimeException re) { return (_trans == null) ? re : _trans.translate(re); } + + /** + * Translate the exception with the failed object. + * + * @param re exception raised by the delegate. + * @param failed the context that failed. + * + * @return the translated exception. If the given input exception had not set + * the failed instance, then sets the given instance as the failed context. + */ + protected RuntimeException translate(RuntimeException re, Object failed) { + if (re instanceof OpenJPAException) { + Object o = ((OpenJPAException) re).getFailedObject(); + if (o == null || "null".equals(o)) { + ((OpenJPAException) re).setFailedObject(Exceptions.toString(failed)); + } + } + return (_trans == null) ? re : _trans.translate(re); + } public Broker getBroker() { return this; @@ -200,7 +221,7 @@ public class DelegatingBroker try { return _broker.find(oid, validate, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, oid); } } @@ -209,7 +230,7 @@ public class DelegatingBroker try { return _broker.findAll(oids, validate, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, oids); } } @@ -217,7 +238,7 @@ public class DelegatingBroker try { return _broker.findCached(oid, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, oid); } } @@ -226,7 +247,7 @@ public class DelegatingBroker try { return _broker.find(oid, fetch, exclude, edata, flags); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, oid); } } @@ -235,7 +256,7 @@ public class DelegatingBroker try { return _broker.findAll(oids, fetch, exclude, edata, flags); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, oids); } } @@ -1071,7 +1092,7 @@ public class DelegatingBroker try { _broker.delete(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1079,7 +1100,7 @@ public class DelegatingBroker try { _broker.deleteAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1087,7 +1108,7 @@ public class DelegatingBroker try { _broker.release(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1095,7 +1116,7 @@ public class DelegatingBroker try { _broker.releaseAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1103,7 +1124,7 @@ public class DelegatingBroker try { _broker.refresh(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1111,7 +1132,7 @@ public class DelegatingBroker try { _broker.refreshAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1119,7 +1140,7 @@ public class DelegatingBroker try { _broker.evict(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1127,7 +1148,7 @@ public class DelegatingBroker try { _broker.evictAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1143,7 +1164,7 @@ public class DelegatingBroker try { _broker.evictAll(extent, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, extent.getElementType()); } } @@ -1151,7 +1172,7 @@ public class DelegatingBroker try { return _broker.detach(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1159,7 +1180,7 @@ public class DelegatingBroker try { return _broker.detachAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1183,7 +1204,7 @@ public class DelegatingBroker try { return _broker.attach(obj, copyNew, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1192,7 +1213,7 @@ public class DelegatingBroker try { return _broker.attachAll(objs, copyNew, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1201,7 +1222,7 @@ public class DelegatingBroker try { _broker.transactional(pc, updateVersion, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, pc); } } @@ -1210,7 +1231,7 @@ public class DelegatingBroker try { _broker.transactionalAll(objs, updateVersion, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1218,7 +1239,7 @@ public class DelegatingBroker try { _broker.nontransactional(pc, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, pc); } } @@ -1226,7 +1247,7 @@ public class DelegatingBroker try { _broker.nontransactionalAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1234,7 +1255,7 @@ public class DelegatingBroker try { return _broker.newExtent(cls, subs); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, cls); } } @@ -1242,7 +1263,7 @@ public class DelegatingBroker try { return _broker.newQuery(language, cls, query); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, query); } } @@ -1250,7 +1271,7 @@ public class DelegatingBroker try { return _broker.newQuery(language, query); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, query); } } @@ -1274,7 +1295,7 @@ public class DelegatingBroker try { _broker.lock(obj, level, timeout, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1282,7 +1303,7 @@ public class DelegatingBroker try { _broker.lock(obj, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, obj); } } @@ -1291,7 +1312,7 @@ public class DelegatingBroker try { _broker.lockAll(objs, level, timeout, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } @@ -1299,7 +1320,7 @@ public class DelegatingBroker try { _broker.lockAll(objs, call); } catch (RuntimeException re) { - throw translate(re); + throw translate(re, objs); } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java index 31d29d8bd..13044a4e2 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/LockException.java @@ -52,6 +52,7 @@ public class LockException super(_loc.get("lock-timeout", Exceptions.toString(failed), String.valueOf(timeout))); setFailedObject(failed); setTimeout(timeout); + setLockLevel(lockLevel); } public int getSubtype() { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java index fbb2f55bd..1c7fe0844 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestTimeoutException.java @@ -15,14 +15,11 @@ package org.apache.openjpa.persistence.query; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; import javax.persistence.EntityManager; import javax.persistence.LockModeType; import javax.persistence.LockTimeoutException; +import javax.persistence.PessimisticLockException; import javax.persistence.Query; import javax.persistence.QueryTimeoutException; @@ -30,6 +27,7 @@ import junit.framework.AssertionFailedError; import org.apache.openjpa.persistence.exception.PObject; import org.apache.openjpa.persistence.test.SingleEMFTestCase; +import org.apache.openjpa.util.OpenJPAException; /** * Tests that correct timeout exceptions are being thrown depending on whether it is a query or a lock operation. @@ -39,7 +37,7 @@ import org.apache.openjpa.persistence.test.SingleEMFTestCase; */ public class TestTimeoutException extends SingleEMFTestCase { private final Class entityClass = PObject.class; - private final ExecutorService scheduler = Executors.newCachedThreadPool(); + public void setUp() { super.setUp(entityClass); } @@ -64,7 +62,7 @@ public class TestTimeoutException extends SingleEMFTestCase { query.getResultList(); fail("Expected " + QueryTimeoutException.class.getName()); } catch (Throwable t) { - assertError(t, QueryTimeoutException.class, timeout); + assertError(t, QueryTimeoutException.class); } assertTrue(em2.getTransaction().isActive()); @@ -90,9 +88,9 @@ public class TestTimeoutException extends SingleEMFTestCase { Map hint = new HashMap(); hint.put("javax.persistence.lock.timeout", timeout); em2.lock(entity2, LockModeType.PESSIMISTIC_WRITE, hint); - fail("Expected " + LockTimeoutException.class.getName()); + fail("Expected " + PessimisticLockException.class.getName()); } catch (Throwable t) { - assertError(t, LockTimeoutException.class, timeout); + assertError(t, PessimisticLockException.class); } assertTrue(em2.getTransaction().isActive()); em2.getTransaction().rollback(); @@ -100,6 +98,29 @@ public class TestTimeoutException extends SingleEMFTestCase { em1.getTransaction().rollback(); } + public void testQueryTimeOutExceptionWhileFindWithLocksOnAlreadyLockedEntities() { + EntityManager em1 = emf.createEntityManager(); + EntityManager em2 = emf.createEntityManager(); + assertNotSame(em1, em2); + Object oid = createEntity(em1); + + em1.getTransaction().begin(); + Object entity = em1.find(entityClass, oid); + assertNotNull(entity); + em1.lock(entity, LockModeType.PESSIMISTIC_WRITE); + + em2.getTransaction().begin(); + try { + em2.find(entityClass, oid, LockModeType.PESSIMISTIC_WRITE); + fail("Expected " + LockTimeoutException.class.getName()); + } catch (Throwable t) { + assertError(t, LockTimeoutException.class); + } + + assertTrue(em2.getTransaction().isActive()); + em2.getTransaction().rollback(); + em1.getTransaction().rollback(); + } public Object createEntity(EntityManager em) { long id = System.nanoTime(); @@ -113,17 +134,36 @@ public class TestTimeoutException extends SingleEMFTestCase { /** - * Assert that an exception of proper type has been thrown by the given task within the given timeout. - * @param t - * @param expeceted + * Assert that an exception of proper type has been thrown. + * Also checks that that the exception has populated the failed object. + * @param actual exception being thrown + * @param expeceted type of the exception */ - void assertError(Throwable actual, Class expected, long timeout) { + void assertError(Throwable actual, Class expected) { if (!expected.isAssignableFrom(actual.getClass())) { actual.printStackTrace(); throw new AssertionFailedError(actual.getClass().getName() + " was raised but expected " + expected.getName()); } - - } + Object failed = getFailedObject(actual); + assertNotNull("Failed object is null", failed); + assertNotEquals("null", failed); + } + + Object getFailedObject(Throwable e) { + if (e instanceof LockTimeoutException) { + return ((LockTimeoutException) e).getObject(); + } + if (e instanceof PessimisticLockException) { + return ((PessimisticLockException) e).getEntity(); + } + if (e instanceof QueryTimeoutException) { + return ((QueryTimeoutException) e).getQuery(); + } + if (e instanceof OpenJPAException) { + return ((OpenJPAException) e).getFailedObject(); + } + return null; + } } diff --git a/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java b/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java index 260f3e281..f6d8d5147 100644 --- a/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java +++ b/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java @@ -108,7 +108,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase { em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, hints); fail("Unexcpected find succeeded. Should throw a PessimisticLockException."); } catch (Throwable e) { - assertError(e, LockTimeoutException.class); + assertError(e, PessimisticLockException.class); } finally { if (em1.getTransaction().isActive()) em1.getTransaction().rollback(); @@ -155,26 +155,26 @@ public class TestPessimisticLocks extends SQLListenerTestCase { public void testFindAfterQueryOrderByWithPessimisticLocks() { EntityManager em1 = emf.createEntityManager(); EntityManager em2 = emf.createEntityManager(); - try { - em1.getTransaction().begin(); - Query query = em1.createQuery("select e from Employee e where e.id < 10 order by e.id").setFirstResult(1); - // Lock all selected Employees, skip the first one, i.e should lock - // Employee(2) - query.setLockMode(LockModeType.PESSIMISTIC_READ); - query.setHint("javax.persistence.query.timeout", 2000); - List q = query.getResultList(); - assertEquals("Expected 1 element with emplyee id=2", q.size(), 1); - assertEquals("Test Employee first name = 'first.2'", q.get(0).getFirstName(), "first.2"); + em1.getTransaction().begin(); + Query query = em1.createQuery("select e from Employee e where e.id < 10 order by e.id").setFirstResult(1); + // Lock all selected Employees, skip the first one, i.e should lock + // Employee(2) + query.setLockMode(LockModeType.PESSIMISTIC_READ); + query.setHint("javax.persistence.query.timeout", 2000); + List q = query.getResultList(); + assertEquals("Expected 1 element with emplyee id=2", q.size(), 1); + assertEquals("Test Employee first name = 'first.2'", q.get(0).getFirstName(), "first.2"); - em2.getTransaction().begin(); - Map map = new HashMap(); - map.put("javax.persistence.lock.timeout", 2000); - // find Employee(2) with a lock, should block and expected a - // PessimisticLockException + em2.getTransaction().begin(); + Map map = new HashMap(); + map.put("javax.persistence.lock.timeout", 2000); + // find Employee(2) with a lock, should block and expected a + // PessimisticLockException + try { em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map); fail("Unexcpected find succeeded. Should throw a PessimisticLockException."); - } catch (LockTimeoutException e) { - assertError(e, LockTimeoutException.class); + } catch (Exception e) { + assertError(e, PessimisticLockException.class); } finally { if (em1.getTransaction().isActive()) em1.getTransaction().rollback(); @@ -183,18 +183,18 @@ public class TestPessimisticLocks extends SQLListenerTestCase { } em1.getTransaction().begin(); - Query query = em1.createQuery("select e.department from Employee e where e.id < 10 order by e.department.id") + query = em1.createQuery("select e.department from Employee e where e.id < 10 order by e.department.id") .setFirstResult(1); // Lock all selected Departments, skip the first one, i.e should // lock Department(20) query.setLockMode(LockModeType.PESSIMISTIC_READ); query.setHint("javax.persistence.query.timeout", 2000); - List q = query.getResultList(); + List result = query.getResultList(); assertEquals("Expected 1 element with department id=20", q.size(), 1); - assertEquals("Test department name = 'D20'", q.get(0).getName(), "D20"); + assertEquals("Test department name = 'D20'", result.get(0).getName(), "D20"); em2.getTransaction().begin(); - Map map = new HashMap(); + map.clear(); map.put("javax.persistence.lock.timeout", 2000); // find Employee(2) with a lock, no block since only department was // locked @@ -258,12 +258,12 @@ public class TestPessimisticLocks extends SQLListenerTestCase { // Lock all selected Employees, skip the first one, i.e should lock // Employee(2) query.setLockMode(LockModeType.PESSIMISTIC_READ); - query.setHint("javax.persistence.query.timeout", 2000); + query.setHint("javax.persistence.query.timeout", 1000); try { List q = query.getResultList(); - fail("Unexcpected find succeeded. Should throw a QueryLockException."); + fail("Unexcpected find succeeded. Should throw a PessimisticLockException."); } catch (Exception e) { - assertError(e, QueryTimeoutException.class); + assertError(e, PessimisticLockException.class); } finally { if (em1.getTransaction().isActive()) em1.getTransaction().rollback(); @@ -314,17 +314,16 @@ public class TestPessimisticLocks extends SQLListenerTestCase { em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map); em1.getTransaction().begin(); - query = em1.createQuery("select e from Employee e where e.id < 10 order by e.department.id") - .setFirstResult(1); + query = em1.createQuery("select e from Employee e where e.id < 10 order by e.department.id").setFirstResult(1); // Lock all selected Employees, skip the first one, i.e should lock // Employee(2) query.setLockMode(LockModeType.PESSIMISTIC_READ); query.setHint("javax.persistence.query.timeout", 2000); try { List q = query.getResultList(); - fail("Unexcpected find succeeded. Should throw a QueryLockException."); + fail("Unexcpected find succeeded. Should throw a PessimisticLockException."); } catch (Exception e) { - assertError(e, QueryTimeoutException.class); + assertError(e, PessimisticLockException.class); } finally { if (em1.getTransaction().isActive()) em1.getTransaction().rollback(); @@ -359,6 +358,9 @@ public class TestPessimisticLocks extends SQLListenerTestCase { if (e instanceof LockTimeoutException) { return ((LockTimeoutException) e).getObject(); } + if (e instanceof PessimisticLockException) { + return ((PessimisticLockException) e).getEntity(); + } if (e instanceof QueryTimeoutException) { return ((QueryTimeoutException) e).getQuery(); } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java index c9c08c804..bf729db38 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/LockTimeoutException.java @@ -45,7 +45,7 @@ public class LockTimeoutException private transient Throwable[] _nested = null; public LockTimeoutException(String msg, Throwable[] nested, Object failed) { - super(msg); + super(msg, nested == null ? null : nested[0], failed); _nested = nested; _failed = failed; } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java index 02a0e86ca..cbd8be4ae 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java @@ -164,14 +164,16 @@ public class PersistenceExceptions } else if (subtype == StoreException.OPTIMISTIC || cause instanceof OptimisticException) { e = new org.apache.openjpa.persistence.OptimisticLockException(msg, nested, failed, fatal); } else if (subtype == StoreException.LOCK || cause instanceof LockException) { - LockException lockEx = (LockException) (ke instanceof LockException ? ke : cause); - if (!lockEx.isFatal()) { - e = new org.apache.openjpa.persistence.LockTimeoutException(msg, nested, failed); - } else if (lockEx != null && lockEx.getLockLevel() >= MixedLockLevels.LOCK_PESSIMISTIC_READ) { - e = new org.apache.openjpa.persistence.PessimisticLockException(msg, nested, failed); - } else { - e = new org.apache.openjpa.persistence.OptimisticLockException(msg, nested, failed, fatal); - } + LockException lockEx = (LockException) (ke instanceof LockException ? ke : cause); + if (lockEx != null && lockEx.getLockLevel() >= MixedLockLevels.LOCK_PESSIMISTIC_READ) { + if (!lockEx.isFatal()) { + e = new org.apache.openjpa.persistence.LockTimeoutException(msg, nested, failed); + } else { + e = new org.apache.openjpa.persistence.PessimisticLockException(msg, nested, failed); + } + } else { + e = new org.apache.openjpa.persistence.OptimisticLockException(msg, nested, failed, fatal); + } } else if (subtype == StoreException.OBJECT_EXISTS || cause instanceof ObjectExistsException) { e = new org.apache.openjpa.persistence.EntityExistsException(msg, nested, failed, fatal); } else if (subtype == StoreException.QUERY || cause instanceof QueryException) { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java index 278e466cf..ad67f161b 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PessimisticLockException.java @@ -46,9 +46,10 @@ public class PessimisticLockException private transient Throwable[] _nested = null; public PessimisticLockException(String msg, Throwable[] nested, Object failed) { - super(msg); + super(msg, nested == null ? null : nested[0], failed); _nested = nested; _failed = failed; + } public int getType() { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java index a52fac074..245b28163 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java @@ -98,8 +98,7 @@ public class QueryImpl implements OpenJPAQuerySPI, Serializable { * @param ret Exception translator for this query * @param query The underlying "kernel" query. */ - public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, - org.apache.openjpa.kernel.Query query) { + public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query) { _em = em; _query = new DelegatingQuery(query, ret); _lock = new ReentrantLock(); @@ -110,8 +109,7 @@ public class QueryImpl implements OpenJPAQuerySPI, Serializable { * * @deprecated */ - public QueryImpl(EntityManagerImpl em, - org.apache.openjpa.kernel.Query query) { + public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) { this(em, null, query); } @@ -1084,4 +1082,9 @@ public class QueryImpl implements OpenJPAQuerySPI, Serializable { } // ================== End of Parameter Processing routines ================================ + + public String toString() { + String result = _query.getQueryString(); + return result != null ? result : _id; + } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java index 5e55615a1..bdb77c2ba 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryTimeoutException.java @@ -25,6 +25,8 @@ import java.io.PrintStream; import java.io.PrintWriter; import java.io.Serializable; +import javax.persistence.Query; + import org.apache.openjpa.util.ExceptionInfo; import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.StoreException; @@ -49,7 +51,7 @@ public class QueryTimeoutException } public QueryTimeoutException(String msg, Throwable[] nested, Object failed, boolean fatal) { - super(msg); + super(msg, nested == null ? null : nested[0], failed instanceof Query ? (Query)failed : null); _nested = nested; _failed = failed; _fatal = fatal;