You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by al...@apache.org on 2011/02/18 17:59:16 UTC
svn commit: r1072061 - in /openjpa/trunk:
openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/
openjpa-kernel/src/main/java/org/apache/openjpa/kernel/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/
openjpa-persisten...
Author: allee8285
Date: Fri Feb 18 16:59:16 2011
New Revision: 1072061
URL: http://svn.apache.org/viewvc?rev=1072061&view=rev
Log:
OPENJPA-1943 - Apply query timeout value to pessimistic row lock statement execution.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerDeadlock.java
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml Fri Feb 18 16:59:16 2011
@@ -47,7 +47,7 @@
</dictionary>
<dictionary class="org.apache.openjpa.jdbc.sql.SQLServerDictionary">
- <lock>1204,1205,1222,HY008</lock>
+ <lock>1204,1205,1222,HY008,40001</lock>
<referential-integrity>544,2601,2627,8114,8115</referential-integrity>
<object-exists>23000</object-exists>
<object-not-found></object-not-found>
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Fri Feb 18 16:59:16 2011
@@ -455,10 +455,14 @@ public class BrokerImpl
}
public FetchConfiguration pushFetchConfiguration() {
+ return pushFetchConfiguration(null);
+ }
+
+ public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc) {
if (_fcs == null)
_fcs = new LinkedList<FetchConfiguration>();
_fcs.add(_fc);
- _fc = (FetchConfiguration) _fc.clone();
+ _fc = (FetchConfiguration) (fc != null ? fc : _fc).clone();
return _fc;
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java Fri Feb 18 16:59:16 2011
@@ -154,6 +154,14 @@ public class DelegatingBroker
}
}
+ public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc) {
+ try {
+ return _broker.pushFetchConfiguration(fc);
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
public void popFetchConfiguration() {
try {
_broker.popFetchConfiguration();
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java Fri Feb 18 16:59:16 2011
@@ -74,6 +74,15 @@ public interface StoreContext {
public FetchConfiguration pushFetchConfiguration();
/**
+ * Pushes the fetch configuration argument onto a stack, and makes the new configuration
+ * the active one.
+ *
+ * @since 2.1.1
+ * @return the new fetch configuration
+ */
+ public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc);
+
+ /**
* Pops the fetch configuration from the top of the stack, making the
* next one down the active one. This returns void to avoid confusion,
* since fetch configurations tend to be used in method-chaining
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/AbstractPersistenceTestCase.java Fri Feb 18 16:59:16 2011
@@ -271,6 +271,12 @@ public abstract class AbstractPersistenc
for (Broker b : ((AbstractBrokerFactory) JPAFacadeHelper.toBrokerFactory(emf)).getOpenBrokers()) {
if (b != null && !b.isClosed()) {
EntityManager em = JPAFacadeHelper.toEntityManager(b);
+ if( em.getTransaction().isActive() ) {
+ try {
+ em.getTransaction().rollback();
+ } catch (Exception e) {
+ }
+ }
closeEM(em);
}
}
Modified: openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java (original)
+++ openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/SequencedActionsTest.java Fri Feb 18 16:59:16 2011
@@ -684,41 +684,93 @@ public abstract class SequencedActionsTe
}
}
}
- String testExClass = null;
- Throwable curThrowable = null;
int threadId = threadToRun;
if (args.length > 1) {
threadId = (Integer) args[1];
}
- TestThread exThread = threads.get(threadId);
- curThrowable = exThread.throwable;
- testExClass = processException(curAction, curThrowable);
-
- boolean exMatched = false;
- if (expectedExceptions != null
- && expectedExceptions.size() > 0) {
- for (Class<?> expectedException :
- expectedExceptions) {
- if (matchExpectedException(curAct, expectedException,
- curThrowable)) {
+ if( threadId != -1 ) {
+ // test exception on a specific thread
+ String testExClass = null;
+ Throwable curThrowable = null;
+ boolean exMatched = false;
+ TestThread exThread = threads.get(threadId);
+ curThrowable = exThread.throwable;
+ testExClass = processException(exThread, curAction, curThrowable);
+
+ if (expectedExceptions != null
+ && expectedExceptions.size() > 0) {
+ for (Class<?> expectedException :
+ expectedExceptions) {
+ if (matchExpectedException(curAct, expectedException,
+ curThrowable)) {
+ exMatched = true;
+ break;
+ }
+ }
+ } else {
+ if (curThrowable == null) {
exMatched = true;
- break;
}
}
- } else {
- if (curThrowable == null) {
- exMatched = true;
- }
- }
- if (!exMatched) {
- log.trace(testExClass);
- if (curThrowable != null) {
- logStack(curThrowable);
+ if (!exMatched) {
+ log.trace(testExClass);
+ if (curThrowable != null) {
+ logStack(curThrowable);
+ }
}
+ assertTrue(curAct + ":Expecting=" + expectedExceptions
+ + ", Testing=" + testExClass, exMatched);
+ exThread.throwable = null;
+ } else {
+ // test exception in any thread; used for deadlock exception testing since db server
+ // decides on which thread to terminate if deadlock is detected.
+ if (expectedExceptions == null || expectedExceptions.size() == 0) {
+ // Expecting no exception in all threads.
+ boolean noExMatched = true;
+ String aTestExClass = "[";
+ for (TestThread aThread : threads) {
+ Throwable aThrowable = aThread.throwable;
+ aTestExClass += processException(aThread, curAction, aThrowable) + ", ";
+ if (aThrowable != null) {
+ noExMatched = false;
+ log.trace(aTestExClass);
+ logStack(aThrowable);
+ aThread.throwable = null;
+ }
+ }
+ assertTrue(curAct + ":Expecting=[no exception]"
+ + ", Testing=" + aTestExClass + ']', noExMatched);
+ } else {
+ // Expecting any exception in any threads.
+ boolean aMatched = false;
+ String aTestExClass = "[";
+ for (TestThread aThread : threads) {
+ Throwable aThrowable = aThread.throwable;
+ aTestExClass += processException(aThread, curAction, aThrowable) + ", ";
+
+ for (Class<?> anExpectedException : expectedExceptions) {
+ if (matchExpectedException(curAct,
+ anExpectedException, aThrowable)) {
+ aMatched = true;
+ break;
+ }
+ }
+ if (aMatched) {
+ break;
+ } else {
+ if (aThrowable != null) {
+ logStack(aThrowable);
+ aThread.throwable = null;
+ }
+ }
+ }
+ if (!aMatched) {
+ log.trace(aTestExClass);
+ }
+ assertTrue(curAct + ":Expecting=" + expectedExceptions
+ + ", Testing=" + aTestExClass + "]", aMatched);
+ }
}
- assertTrue(curAct + ":Expecting=" + expectedExceptions
- + ", Testing=" + testExClass, exMatched);
- exThread.throwable = null;
break;
case WaitAllChildren:
@@ -855,7 +907,7 @@ public abstract class SequencedActionsTe
log.trace("finally: commit completed");
}
} catch(Exception finalEx) {
- String failStr = processException(curAction, finalEx);
+ String failStr = processException(thisThread, curAction, finalEx);
log.trace("Fincally:" + failStr);
}
}
@@ -881,11 +933,11 @@ public abstract class SequencedActionsTe
return lockMode;
}
- private String processException(Act curAction, Throwable t) {
- String failStr = "Caught exception: none";
+ private String processException(TestThread thread, Act curAction, Throwable t) {
+ String failStr = "[" + thread.threadToRun + "] Caught exception: none";
if (t != null) {
getLog().trace(
- "Caught exception: " + t.getClass().getName() + ":" + t);
+ "[" + thread.threadToRun + "] Caught exception: " + t.getClass().getName() + ":" + t);
logStack(t);
Throwable rootCause = t.getCause();
failStr = "Failed on action '" + curAction + "' with exception "
Modified: openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerDeadlock.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerDeadlock.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerDeadlock.java (original)
+++ openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerDeadlock.java Fri Feb 18 16:59:16 2011
@@ -19,6 +19,7 @@
package org.apache.openjpa.persistence.lockmgr;
import java.util.Arrays;
+import java.util.HashMap;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
@@ -28,12 +29,14 @@ import javax.persistence.LockModeType;
*/
public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
private DBType dbType;
+ private HashMap<DBType,Class<?>[]> expWriteLockExClasses;
public void setUp() {
setSupportedDatabases(
+ org.apache.openjpa.jdbc.sql.DB2Dictionary.class,
org.apache.openjpa.jdbc.sql.DerbyDictionary.class,
org.apache.openjpa.jdbc.sql.OracleDictionary.class,
- org.apache.openjpa.jdbc.sql.DB2Dictionary.class);
+ org.apache.openjpa.jdbc.sql.SQLServerDictionary.class);
if (isTestsDisabled()) {
return;
}
@@ -41,6 +44,12 @@ public class TestMixedLockManagerDeadloc
setUp(LockEmployee.class
, "openjpa.LockManager", "mixed"
);
+ expWriteLockExClasses = new HashMap<DBType,Class<?>[]>();
+ expWriteLockExClasses.put(DBType.db2, null);
+ expWriteLockExClasses.put(DBType.derby, ExpectingOptimisticLockExClass);
+ expWriteLockExClasses.put(DBType.oracle, null);
+ expWriteLockExClasses.put(DBType.sqlserver, ExpectingOptimisticLockExClass);
+
commonSetUp();
EntityManager em = emf.createEntityManager();
dbType = getDBType(em);
@@ -49,8 +58,7 @@ public class TestMixedLockManagerDeadloc
/* ======== Find dead lock exception test ============*/
public void testFindDeadLockException() {
commonFindTest("testFindDeadLockException", LockModeType.READ, null);
- commonFindTest("testFindDeadLockException", LockModeType.WRITE, dbType == DBType.oracle ? null
- : ExpectingOptimisticLockExClass);
+ commonFindTest("testFindDeadLockException", LockModeType.WRITE, expWriteLockExClasses.get(dbType));
commonFindTest("testFindDeadLockException", LockModeType.PESSIMISTIC_WRITE, ExpectingAnyLockExClass);
}
@@ -73,7 +81,7 @@ public class TestMixedLockManagerDeadloc
{Act.FindWithLock, 2, t1Lock},
{Act.WaitAllChildren},
- {Act.TestException, 1, t1Exceptions},
+ {Act.TestException, -1, t1Exceptions}, // test t1Exceptions in any thread
{Act.RollbackTx}
};
Object[][] thread1 = {
@@ -94,10 +102,8 @@ public class TestMixedLockManagerDeadloc
/* ======== named query dead lock exception test ============*/
public void testNamedQueryDeadLockException() {
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.READ, null);
- commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.WRITE, dbType == DBType.oracle ? null
- : ExpectingOptimisticLockExClass);
-// commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.PESSIMISTIC_FORCE_INCREMENT,
-// ExpectingAnyLockExClass);
+ commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.WRITE, expWriteLockExClasses.get(dbType));
+ commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.PESSIMISTIC_FORCE_INCREMENT, ExpectingAnyLockExClass);
}
private void commonNamedQueryTest( String testName,
@@ -119,7 +125,7 @@ public class TestMixedLockManagerDeadloc
{Act.NamedQueryWithLock, "findEmployeeById", 2, t1Lock, "openjpa.hint.IgnorePreparedQuery", true},
{Act.WaitAllChildren},
- {Act.TestException, 1, t1Exceptions},
+ {Act.TestException, -1, t1Exceptions},
{Act.RollbackTx},
{Act.CloseEm}
Modified: openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java (original)
+++ openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java Fri Feb 18 16:59:16 2011
@@ -137,10 +137,7 @@ public class TestPessimisticLocks extend
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, hints);
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (Throwable e) {
- if (!dict.supportsLockingWithMultipleTables)
- assertError(e, PessimisticLockException.class);
- else
- assertError(e, LockTimeoutException.class);
+ assertError(e, PessimisticLockException.class, LockTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -206,10 +203,7 @@ public class TestPessimisticLocks extend
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (Exception e) {
- if (!dict.supportsLockingWithMultipleTables)
- assertError(e, PessimisticLockException.class);
- else
- assertError(e, LockTimeoutException.class);
+ assertError(e, PessimisticLockException.class, LockTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -276,10 +270,7 @@ public class TestPessimisticLocks extend
assertTrue("Test department name = 'D20'", q.get(0).getName().equals("D10")
|| q.get(0).getName().equals("D20"));
} catch (Exception ex) {
- if (!dict.supportsLockingWithMultipleTables)
- fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
- else
- assertError(ex, QueryTimeoutException.class);
+ assertError(ex, QueryTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -304,10 +295,7 @@ public class TestPessimisticLocks extend
List<Employee> q = query.getResultList();
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (Exception e) {
- if (!dict.supportsLockingWithMultipleTables)
- assertError(e, PessimisticLockException.class);
- else
- assertError(e, QueryTimeoutException.class);
+ assertError(e, PessimisticLockException.class, QueryTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -342,10 +330,7 @@ public class TestPessimisticLocks extend
assertEquals("Expected 1 element with department id=20", q.size(), 1);
assertEquals("Test department name = 'D20'", q.get(0).getName(), "D20");
} catch (Exception ex) {
- if (!dict.supportsLockingWithMultipleTables)
- fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
- else
- assertError(ex, QueryTimeoutException.class);
+ assertError(ex, QueryTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -370,10 +355,7 @@ public class TestPessimisticLocks extend
List<?> q = query.getResultList();
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (Exception e) {
- if (!dict.supportsLockingWithMultipleTables)
- assertError(e, PessimisticLockException.class);
- else
- assertError(e, QueryTimeoutException.class);
+ assertError(e, PessimisticLockException.class, QueryTimeoutException.class);
} finally {
if (em1.getTransaction().isActive())
em1.getTransaction().rollback();
@@ -505,12 +487,22 @@ public class TestPessimisticLocks extend
* @param expeceted
* type of the exception
*/
- void assertError(Throwable actual, Class<? extends Throwable> expected) {
- if (!expected.isAssignableFrom(actual.getClass())) {
- actual.printStackTrace();
- throw new AssertionFailedError(actual.getClass().getName() + " was raised but expected "
- + expected.getName());
- }
+ void assertError(Throwable actual, Class<? extends Throwable> ... expected) {
+ boolean matched = false;
+ String expectedNames = "";
+ for (Class<? extends Throwable> aExpected : expected) {
+ expectedNames += aExpected.getName() + ", ";
+ if (aExpected.isAssignableFrom(actual.getClass())) {
+ matched = true;
+ }
+ }
+ if (!matched) {
+ actual.printStackTrace();
+ throw new AssertionFailedError(actual.getClass().getName()
+ + " was raised but expecting one of the following: ["
+ + expectedNames.substring(0, expectedNames.length() - 2) + "]");
+ }
+
Object failed = getFailedObject(actual);
assertNotNull("Failed object is null", failed);
assertNotEquals("null", failed);
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Fri Feb 18 16:59:16 2011
@@ -163,10 +163,14 @@ public class EntityManagerImpl
}
public FetchPlan pushFetchPlan() {
+ return pushFetchPlan(null);
+ }
+
+ public FetchPlan pushFetchPlan(FetchConfiguration fc) {
assertNotCloseInvoked();
_broker.lock();
try {
- _broker.pushFetchConfiguration();
+ _broker.pushFetchConfiguration(fc);
return getFetchPlan();
} finally {
_broker.unlock();
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=1072061&r1=1072060&r2=1072061&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Fri Feb 18 16:59:16 2011
@@ -316,22 +316,26 @@ public class QueryImpl<X> implements Ope
public List getResultList() {
_em.assertNotCloseInvoked();
- Object ob = execute();
- if (ob instanceof List) {
- List ret = (List) ob;
- if (ret instanceof ResultList) {
- RuntimeExceptionTranslator trans = PersistenceExceptions.getRollbackTranslator(_em);
- if (_query.isDistinct()) {
- return new DistinctResultList((ResultList) ret, trans);
+ boolean queryFetchPlanUsed = pushQueryFetchPlan();
+ try {
+ Object ob = execute();
+ if (ob instanceof List) {
+ List ret = (List) ob;
+ if (ret instanceof ResultList) {
+ RuntimeExceptionTranslator trans = PersistenceExceptions.getRollbackTranslator(_em);
+ if (_query.isDistinct()) {
+ return new DistinctResultList((ResultList) ret, trans);
+ } else {
+ return new DelegatingResultList((ResultList) ret, trans);
+ }
} else {
- return new DelegatingResultList((ResultList) ret, trans);
+ return ret;
}
- } else {
- return ret;
- }
+ }
+ return Collections.singletonList(ob);
+ } finally {
+ popQueryFetchPlan(queryFetchPlanUsed);
}
-
- return Collections.singletonList(ob);
}
/**
@@ -340,18 +344,45 @@ public class QueryImpl<X> implements Ope
public X getSingleResult() {
_em.assertNotCloseInvoked();
setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
- List result = getResultList();
- if (result == null || result.isEmpty())
- throw new NoResultException(_loc.get("no-result", getQueryString())
- .getMessage());
- if (result.size() > 1)
- throw new NonUniqueResultException(_loc.get("non-unique-result",
- getQueryString(), result.size()).getMessage());
+ boolean queryFetchPlanUsed = pushQueryFetchPlan();
try {
- return (X)result.get(0);
- } catch (Exception e) {
- throw new NoResultException(_loc.get("no-result", getQueryString())
- .getMessage());
+ List result = getResultList();
+ if (result == null || result.isEmpty())
+ throw new NoResultException(_loc.get("no-result", getQueryString())
+ .getMessage());
+ if (result.size() > 1)
+ throw new NonUniqueResultException(_loc.get("non-unique-result",
+ getQueryString(), result.size()).getMessage());
+ try {
+ return (X)result.get(0);
+ } catch (Exception e) {
+ throw new NoResultException(_loc.get("no-result", getQueryString())
+ .getMessage());
+ }
+ } finally {
+ popQueryFetchPlan(queryFetchPlanUsed);
+ }
+ }
+
+ private boolean pushQueryFetchPlan() {
+ boolean fcPushed = false;
+ if (_fetch != null && _hintHandler != null) {
+ switch (_fetch.getReadLockMode()) {
+ case PESSIMISTIC_READ:
+ case PESSIMISTIC_WRITE:
+ case PESSIMISTIC_FORCE_INCREMENT:
+ // push query fetch plan to em if pessisimistic lock and any
+ // hints are set
+ _em.pushFetchPlan(((FetchPlanImpl)_fetch).getDelegate());
+ fcPushed = true;
+ }
+ }
+ return fcPushed;
+ }
+
+ private void popQueryFetchPlan(boolean queryFetchPlanUsed) {
+ if (queryFetchPlanUsed) {
+ _em.popFetchPlan();
}
}