mirror of https://github.com/apache/openjpa.git
OPENJPA-1943 - Apply query timeout value to pessimistic row lock statement execution.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1072061 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cf4a80047e
commit
0c37fc6e57
|
@ -47,7 +47,7 @@
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
||||||
<dictionary class="org.apache.openjpa.jdbc.sql.SQLServerDictionary">
|
<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>
|
<referential-integrity>544,2601,2627,8114,8115</referential-integrity>
|
||||||
<object-exists>23000</object-exists>
|
<object-exists>23000</object-exists>
|
||||||
<object-not-found></object-not-found>
|
<object-not-found></object-not-found>
|
||||||
|
|
|
@ -455,10 +455,14 @@ public class BrokerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
public FetchConfiguration pushFetchConfiguration() {
|
public FetchConfiguration pushFetchConfiguration() {
|
||||||
|
return pushFetchConfiguration(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FetchConfiguration pushFetchConfiguration(FetchConfiguration fc) {
|
||||||
if (_fcs == null)
|
if (_fcs == null)
|
||||||
_fcs = new LinkedList<FetchConfiguration>();
|
_fcs = new LinkedList<FetchConfiguration>();
|
||||||
_fcs.add(_fc);
|
_fcs.add(_fc);
|
||||||
_fc = (FetchConfiguration) _fc.clone();
|
_fc = (FetchConfiguration) (fc != null ? fc : _fc).clone();
|
||||||
return _fc;
|
return _fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
public void popFetchConfiguration() {
|
||||||
try {
|
try {
|
||||||
_broker.popFetchConfiguration();
|
_broker.popFetchConfiguration();
|
||||||
|
|
|
@ -73,6 +73,15 @@ public interface StoreContext {
|
||||||
*/
|
*/
|
||||||
public FetchConfiguration pushFetchConfiguration();
|
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
|
* Pops the fetch configuration from the top of the stack, making the
|
||||||
* next one down the active one. This returns void to avoid confusion,
|
* next one down the active one. This returns void to avoid confusion,
|
||||||
|
|
|
@ -271,6 +271,12 @@ public abstract class AbstractPersistenceTestCase extends TestCase {
|
||||||
for (Broker b : ((AbstractBrokerFactory) JPAFacadeHelper.toBrokerFactory(emf)).getOpenBrokers()) {
|
for (Broker b : ((AbstractBrokerFactory) JPAFacadeHelper.toBrokerFactory(emf)).getOpenBrokers()) {
|
||||||
if (b != null && !b.isClosed()) {
|
if (b != null && !b.isClosed()) {
|
||||||
EntityManager em = JPAFacadeHelper.toEntityManager(b);
|
EntityManager em = JPAFacadeHelper.toEntityManager(b);
|
||||||
|
if( em.getTransaction().isActive() ) {
|
||||||
|
try {
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
closeEM(em);
|
closeEM(em);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -684,41 +684,93 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String testExClass = null;
|
|
||||||
Throwable curThrowable = null;
|
|
||||||
int threadId = threadToRun;
|
int threadId = threadToRun;
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
threadId = (Integer) args[1];
|
threadId = (Integer) args[1];
|
||||||
}
|
}
|
||||||
TestThread exThread = threads.get(threadId);
|
if( threadId != -1 ) {
|
||||||
curThrowable = exThread.throwable;
|
// test exception on a specific thread
|
||||||
testExClass = processException(curAction, curThrowable);
|
String testExClass = null;
|
||||||
|
Throwable curThrowable = null;
|
||||||
|
boolean exMatched = false;
|
||||||
|
TestThread exThread = threads.get(threadId);
|
||||||
|
curThrowable = exThread.throwable;
|
||||||
|
testExClass = processException(exThread, curAction, curThrowable);
|
||||||
|
|
||||||
boolean exMatched = false;
|
if (expectedExceptions != null
|
||||||
if (expectedExceptions != null
|
&& expectedExceptions.size() > 0) {
|
||||||
&& expectedExceptions.size() > 0) {
|
for (Class<?> expectedException :
|
||||||
for (Class<?> expectedException :
|
expectedExceptions) {
|
||||||
expectedExceptions) {
|
if (matchExpectedException(curAct, expectedException,
|
||||||
if (matchExpectedException(curAct, expectedException,
|
curThrowable)) {
|
||||||
curThrowable)) {
|
exMatched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (curThrowable == null) {
|
||||||
exMatched = true;
|
exMatched = true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!exMatched) {
|
||||||
|
log.trace(testExClass);
|
||||||
|
if (curThrowable != null) {
|
||||||
|
logStack(curThrowable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(curAct + ":Expecting=" + expectedExceptions
|
||||||
|
+ ", Testing=" + testExClass, exMatched);
|
||||||
|
exThread.throwable = null;
|
||||||
} else {
|
} else {
|
||||||
if (curThrowable == null) {
|
// test exception in any thread; used for deadlock exception testing since db server
|
||||||
exMatched = true;
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!exMatched) {
|
|
||||||
log.trace(testExClass);
|
|
||||||
if (curThrowable != null) {
|
|
||||||
logStack(curThrowable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertTrue(curAct + ":Expecting=" + expectedExceptions
|
|
||||||
+ ", Testing=" + testExClass, exMatched);
|
|
||||||
exThread.throwable = null;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WaitAllChildren:
|
case WaitAllChildren:
|
||||||
|
@ -855,7 +907,7 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
|
||||||
log.trace("finally: commit completed");
|
log.trace("finally: commit completed");
|
||||||
}
|
}
|
||||||
} catch(Exception finalEx) {
|
} catch(Exception finalEx) {
|
||||||
String failStr = processException(curAction, finalEx);
|
String failStr = processException(thisThread, curAction, finalEx);
|
||||||
log.trace("Fincally:" + failStr);
|
log.trace("Fincally:" + failStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -881,11 +933,11 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
|
||||||
return lockMode;
|
return lockMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String processException(Act curAction, Throwable t) {
|
private String processException(TestThread thread, Act curAction, Throwable t) {
|
||||||
String failStr = "Caught exception: none";
|
String failStr = "[" + thread.threadToRun + "] Caught exception: none";
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
getLog().trace(
|
getLog().trace(
|
||||||
"Caught exception: " + t.getClass().getName() + ":" + t);
|
"[" + thread.threadToRun + "] Caught exception: " + t.getClass().getName() + ":" + t);
|
||||||
logStack(t);
|
logStack(t);
|
||||||
Throwable rootCause = t.getCause();
|
Throwable rootCause = t.getCause();
|
||||||
failStr = "Failed on action '" + curAction + "' with exception "
|
failStr = "Failed on action '" + curAction + "' with exception "
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.openjpa.persistence.lockmgr;
|
package org.apache.openjpa.persistence.lockmgr;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
|
@ -28,12 +29,14 @@ import javax.persistence.LockModeType;
|
||||||
*/
|
*/
|
||||||
public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
private DBType dbType;
|
private DBType dbType;
|
||||||
|
private HashMap<DBType,Class<?>[]> expWriteLockExClasses;
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
setSupportedDatabases(
|
setSupportedDatabases(
|
||||||
|
org.apache.openjpa.jdbc.sql.DB2Dictionary.class,
|
||||||
org.apache.openjpa.jdbc.sql.DerbyDictionary.class,
|
org.apache.openjpa.jdbc.sql.DerbyDictionary.class,
|
||||||
org.apache.openjpa.jdbc.sql.OracleDictionary.class,
|
org.apache.openjpa.jdbc.sql.OracleDictionary.class,
|
||||||
org.apache.openjpa.jdbc.sql.DB2Dictionary.class);
|
org.apache.openjpa.jdbc.sql.SQLServerDictionary.class);
|
||||||
if (isTestsDisabled()) {
|
if (isTestsDisabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +44,12 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
setUp(LockEmployee.class
|
setUp(LockEmployee.class
|
||||||
, "openjpa.LockManager", "mixed"
|
, "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();
|
commonSetUp();
|
||||||
EntityManager em = emf.createEntityManager();
|
EntityManager em = emf.createEntityManager();
|
||||||
dbType = getDBType(em);
|
dbType = getDBType(em);
|
||||||
|
@ -49,8 +58,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
/* ======== Find dead lock exception test ============*/
|
/* ======== Find dead lock exception test ============*/
|
||||||
public void testFindDeadLockException() {
|
public void testFindDeadLockException() {
|
||||||
commonFindTest("testFindDeadLockException", LockModeType.READ, null);
|
commonFindTest("testFindDeadLockException", LockModeType.READ, null);
|
||||||
commonFindTest("testFindDeadLockException", LockModeType.WRITE, dbType == DBType.oracle ? null
|
commonFindTest("testFindDeadLockException", LockModeType.WRITE, expWriteLockExClasses.get(dbType));
|
||||||
: ExpectingOptimisticLockExClass);
|
|
||||||
commonFindTest("testFindDeadLockException", LockModeType.PESSIMISTIC_WRITE, ExpectingAnyLockExClass);
|
commonFindTest("testFindDeadLockException", LockModeType.PESSIMISTIC_WRITE, ExpectingAnyLockExClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +81,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
{Act.FindWithLock, 2, t1Lock},
|
{Act.FindWithLock, 2, t1Lock},
|
||||||
|
|
||||||
{Act.WaitAllChildren},
|
{Act.WaitAllChildren},
|
||||||
{Act.TestException, 1, t1Exceptions},
|
{Act.TestException, -1, t1Exceptions}, // test t1Exceptions in any thread
|
||||||
{Act.RollbackTx}
|
{Act.RollbackTx}
|
||||||
};
|
};
|
||||||
Object[][] thread1 = {
|
Object[][] thread1 = {
|
||||||
|
@ -94,10 +102,8 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
/* ======== named query dead lock exception test ============*/
|
/* ======== named query dead lock exception test ============*/
|
||||||
public void testNamedQueryDeadLockException() {
|
public void testNamedQueryDeadLockException() {
|
||||||
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.READ, null);
|
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.READ, null);
|
||||||
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.WRITE, dbType == DBType.oracle ? null
|
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.WRITE, expWriteLockExClasses.get(dbType));
|
||||||
: ExpectingOptimisticLockExClass);
|
commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.PESSIMISTIC_FORCE_INCREMENT, ExpectingAnyLockExClass);
|
||||||
// commonNamedQueryTest("testNamedQueryDeadLockException", LockModeType.PESSIMISTIC_FORCE_INCREMENT,
|
|
||||||
// ExpectingAnyLockExClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void commonNamedQueryTest( String testName,
|
private void commonNamedQueryTest( String testName,
|
||||||
|
@ -119,7 +125,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
|
||||||
{Act.NamedQueryWithLock, "findEmployeeById", 2, t1Lock, "openjpa.hint.IgnorePreparedQuery", true},
|
{Act.NamedQueryWithLock, "findEmployeeById", 2, t1Lock, "openjpa.hint.IgnorePreparedQuery", true},
|
||||||
|
|
||||||
{Act.WaitAllChildren},
|
{Act.WaitAllChildren},
|
||||||
{Act.TestException, 1, t1Exceptions},
|
{Act.TestException, -1, t1Exceptions},
|
||||||
|
|
||||||
{Act.RollbackTx},
|
{Act.RollbackTx},
|
||||||
{Act.CloseEm}
|
{Act.CloseEm}
|
||||||
|
|
|
@ -137,10 +137,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, hints);
|
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, hints);
|
||||||
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(e, PessimisticLockException.class, LockTimeoutException.class);
|
||||||
assertError(e, PessimisticLockException.class);
|
|
||||||
else
|
|
||||||
assertError(e, LockTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -206,10 +203,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
|
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
|
||||||
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(e, PessimisticLockException.class, LockTimeoutException.class);
|
||||||
assertError(e, PessimisticLockException.class);
|
|
||||||
else
|
|
||||||
assertError(e, LockTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -276,10 +270,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
assertTrue("Test department name = 'D20'", q.get(0).getName().equals("D10")
|
assertTrue("Test department name = 'D20'", q.get(0).getName().equals("D10")
|
||||||
|| q.get(0).getName().equals("D20"));
|
|| q.get(0).getName().equals("D20"));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(ex, QueryTimeoutException.class);
|
||||||
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
|
|
||||||
else
|
|
||||||
assertError(ex, QueryTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -304,10 +295,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
List<Employee> q = query.getResultList();
|
List<Employee> q = query.getResultList();
|
||||||
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(e, PessimisticLockException.class, QueryTimeoutException.class);
|
||||||
assertError(e, PessimisticLockException.class);
|
|
||||||
else
|
|
||||||
assertError(e, QueryTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -342,10 +330,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
assertEquals("Expected 1 element with department id=20", q.size(), 1);
|
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'", q.get(0).getName(), "D20");
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(ex, QueryTimeoutException.class);
|
||||||
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
|
|
||||||
else
|
|
||||||
assertError(ex, QueryTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -370,10 +355,7 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
List<?> q = query.getResultList();
|
List<?> q = query.getResultList();
|
||||||
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (!dict.supportsLockingWithMultipleTables)
|
assertError(e, PessimisticLockException.class, QueryTimeoutException.class);
|
||||||
assertError(e, PessimisticLockException.class);
|
|
||||||
else
|
|
||||||
assertError(e, QueryTimeoutException.class);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (em1.getTransaction().isActive())
|
if (em1.getTransaction().isActive())
|
||||||
em1.getTransaction().rollback();
|
em1.getTransaction().rollback();
|
||||||
|
@ -505,12 +487,22 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
|
||||||
* @param expeceted
|
* @param expeceted
|
||||||
* type of the exception
|
* type of the exception
|
||||||
*/
|
*/
|
||||||
void assertError(Throwable actual, Class<? extends Throwable> expected) {
|
void assertError(Throwable actual, Class<? extends Throwable> ... expected) {
|
||||||
if (!expected.isAssignableFrom(actual.getClass())) {
|
boolean matched = false;
|
||||||
actual.printStackTrace();
|
String expectedNames = "";
|
||||||
throw new AssertionFailedError(actual.getClass().getName() + " was raised but expected "
|
for (Class<? extends Throwable> aExpected : expected) {
|
||||||
+ expected.getName());
|
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);
|
Object failed = getFailedObject(actual);
|
||||||
assertNotNull("Failed object is null", failed);
|
assertNotNull("Failed object is null", failed);
|
||||||
assertNotEquals("null", failed);
|
assertNotEquals("null", failed);
|
||||||
|
|
|
@ -163,10 +163,14 @@ public class EntityManagerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
public FetchPlan pushFetchPlan() {
|
public FetchPlan pushFetchPlan() {
|
||||||
|
return pushFetchPlan(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FetchPlan pushFetchPlan(FetchConfiguration fc) {
|
||||||
assertNotCloseInvoked();
|
assertNotCloseInvoked();
|
||||||
_broker.lock();
|
_broker.lock();
|
||||||
try {
|
try {
|
||||||
_broker.pushFetchConfiguration();
|
_broker.pushFetchConfiguration(fc);
|
||||||
return getFetchPlan();
|
return getFetchPlan();
|
||||||
} finally {
|
} finally {
|
||||||
_broker.unlock();
|
_broker.unlock();
|
||||||
|
|
|
@ -316,22 +316,26 @@ public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
|
||||||
|
|
||||||
public List getResultList() {
|
public List getResultList() {
|
||||||
_em.assertNotCloseInvoked();
|
_em.assertNotCloseInvoked();
|
||||||
Object ob = execute();
|
boolean queryFetchPlanUsed = pushQueryFetchPlan();
|
||||||
if (ob instanceof List) {
|
try {
|
||||||
List ret = (List) ob;
|
Object ob = execute();
|
||||||
if (ret instanceof ResultList) {
|
if (ob instanceof List) {
|
||||||
RuntimeExceptionTranslator trans = PersistenceExceptions.getRollbackTranslator(_em);
|
List ret = (List) ob;
|
||||||
if (_query.isDistinct()) {
|
if (ret instanceof ResultList) {
|
||||||
return new DistinctResultList((ResultList) ret, trans);
|
RuntimeExceptionTranslator trans = PersistenceExceptions.getRollbackTranslator(_em);
|
||||||
|
if (_query.isDistinct()) {
|
||||||
|
return new DistinctResultList((ResultList) ret, trans);
|
||||||
|
} else {
|
||||||
|
return new DelegatingResultList((ResultList) ret, trans);
|
||||||
|
}
|
||||||
} else {
|
} 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 OpenJPAQuerySPI<X>, Serializable {
|
||||||
public X getSingleResult() {
|
public X getSingleResult() {
|
||||||
_em.assertNotCloseInvoked();
|
_em.assertNotCloseInvoked();
|
||||||
setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
|
setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
|
||||||
List result = getResultList();
|
boolean queryFetchPlanUsed = pushQueryFetchPlan();
|
||||||
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 {
|
try {
|
||||||
return (X)result.get(0);
|
List result = getResultList();
|
||||||
} catch (Exception e) {
|
if (result == null || result.isEmpty())
|
||||||
throw new NoResultException(_loc.get("no-result", getQueryString())
|
throw new NoResultException(_loc.get("no-result", getQueryString())
|
||||||
.getMessage());
|
.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue