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();
 		}
 	}