OPENJPA-1402 - Improve concurrency by not locking relation field whenever appropriate for mixed lock manager.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@884744 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Albert Lee 2009-11-27 05:11:21 +00:00
parent a1221ea36d
commit cbbe382ecd
16 changed files with 444 additions and 177 deletions

View File

@ -46,4 +46,9 @@ public interface JDBCLockManager
* produced by a FOR UPDATE select.
*/
public void loadedForUpdate(OpenJPAStateManager sm);
/**
* Return true if locking is not desired for relation fields.
*/
public boolean skipRelationFieldLock();
}

View File

@ -128,4 +128,8 @@ public class MixedLockManager extends PessimisticLockManager {
}
}
}
public boolean skipRelationFieldLock() {
return true;
}
}

View File

@ -24,7 +24,6 @@ import java.util.Map;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StoreManager;

View File

@ -23,6 +23,7 @@ import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Comparator;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.VersionMappingInfo;
@ -34,6 +35,7 @@ import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.Row;
import org.apache.openjpa.jdbc.sql.RowManager;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.MixedLockLevels;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StoreManager;
import org.apache.openjpa.lib.util.Localizer;
@ -277,7 +279,13 @@ public abstract class ColumnVersionStrategy
sel.select(cols);
sel.wherePrimaryKey(sm.getObjectId(), vers.getClassMapping(), store);
Result res = sel.execute(store, null);
// No need to lock version field (i.e. optimistic), except when version update is required (e.g. refresh)
JDBCFetchConfiguration fetch = store.getFetchConfiguration();
if (!updateVersion && fetch.getReadLockLevel() >= MixedLockLevels.LOCK_PESSIMISTIC_READ) {
fetch = (JDBCFetchConfiguration) fetch.clone();
fetch.setReadLockLevel(MixedLockLevels.LOCK_NONE);
}
Result res = sel.execute(store, fetch);
try {
if (!res.next())
return false;

View File

@ -30,6 +30,7 @@ import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.ReflectingPersistenceCapable;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.kernel.MixedLockManager;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.Embeddable;
import org.apache.openjpa.jdbc.meta.FieldMapping;
@ -53,6 +54,7 @@ import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.jdbc.sql.Union;
import org.apache.openjpa.kernel.LockManager;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
@ -65,6 +67,7 @@ import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.OpenJPAId;
import org.apache.openjpa.util.UnsupportedException;
import serp.util.Numbers;
/**
@ -699,8 +702,14 @@ public class RelationFieldStrategy
}
}
boolean isLocked = res.isLocking();
try {
res.setLocking(store.getLockManager().skipRelationFieldLock());
sm.storeObject(field.getIndex(), res.load(cls, store, fetch,
eagerJoin(res.newJoins(), cls, false)));
} finally {
res.setLocking(isLocked);
}
// reset mapped by is needed for OneToOne bidirectional relations
// having a mapped-by parent to correctly set the parent-child

View File

@ -97,6 +97,10 @@ public class MergedResult
_res[i].close();
}
public void setLocking(boolean locking) {
_res[_idx].setLocking(locking);
}
public boolean isLocking() {
return _res[_idx].isLocking();
}

View File

@ -78,6 +78,11 @@ public interface Result
*/
public void close();
/**
* Set to true if row locking has been issued for the row.
*/
public void setLocking(boolean locking);
/**
* If true, then any results loaded from this Result
* will be locked in the database.

View File

@ -57,7 +57,7 @@ public abstract class AbstractLockManager
*/
public void lockAll(Collection sms, int level, int timeout,
Object context) {
for (Iterator itr = sms.iterator(); itr.hasNext();)
for (Iterator<?> itr = sms.iterator(); itr.hasNext();)
lock((OpenJPAStateManager) itr.next(), level, timeout, context);
}
@ -76,8 +76,14 @@ public abstract class AbstractLockManager
/**
* Does nothing by default.
*/
public void close ()
{
public void close () {
}
/**
* Default not to skip relation field to maintain PessimisticLockManager semantics.
*/
public boolean skipRelationFieldLock() {
return false;
}
}

View File

@ -68,6 +68,7 @@ public abstract class LockScopeTestCase extends SQLListenerTestCase {
protected final String Any = ".*";
protected final String Select = "SELECT.*FROM.*";
protected final String SelectVersion = "SELECT.*version.*FROM.*";
protected final String Where = ".*WHERE.*";
// protected final String Join = ".*(JOIN){1}.*";
protected final String NoJoin = "(JOIN){0}";
@ -155,6 +156,15 @@ public abstract class LockScopeTestCase extends SQLListenerTestCase {
assertAllSQLAnyOrder(expected);
}
public void assertLockTestNoSQLs(String... expected) {
Log log = getDumpSQLLog();
if( log.isTraceEnabled()) {
log.trace("\r\n" + toString(sql));
return;
}
assertNoneSQLAnyOrder(expected);
}
protected void logStack(Throwable t) {
StringWriter str = new StringWriter();
PrintWriter print = new PrintWriter(str);

View File

@ -43,8 +43,8 @@ public class Test1x1LockScope extends LockScopeTestCase {
, LSE1x1LfJT.class
, LSE1x1LfJTLzy.class
, LSE1x1Rt.class
, "openjpa.LockManager", "mixed",
"openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)"
, "openjpa.LockManager", "mixed"
, "openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)"
);
commonSetUp(LSE1x1Lf.class
, LSE1x1LfLzy.class
@ -138,12 +138,18 @@ public class Test1x1LockScope extends LockScopeTestCase {
case db2:
// SELECT t0.version, t0.firstName, t1.id, t1.version, t1.lastName FROM LSE1x1Lf t0
// LEFT OUTER JOIN LSE1x1Rt t1 ON t0.UNIRIGHT_ID = t1.id WHERE t0.id = ?
// optimize for 1 row FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1111202]
// optimize for 1 row FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS
// [params=(int) 1111202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ?
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1121202]
// -FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS- [params=(int) 1121202]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ?
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1111202]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
// -FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS- [params=(int) 1111202]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: if jpa2, DO NOT lock LSE1x1RT using "FOR UPDATE OF col"
// SELECT t0.version, t0.firstName, t1.id, t1.version, t1.lastName
@ -154,20 +160,25 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableRtName + Where + "\\(\\+\\).*"
+ ForUpdate);
break;
case derby: //TODO: **Non-atomic lock.
case derby: //-TODO: **Non-atomic lock.
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
// another transaction could modify the data before the lock is obtained.
// SELECT t0.version, t0.firstName, t1.id, t1.version, t1.lastName FROM LSE1x1Lf t0
// LEFT OUTER JOIN LSE1x1Rt t1 ON t0.UNIRIGHT_ID = t1.id WHERE t0.id = ?
// [params=(int) 1111202]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? -FOR UPDATE WITH RR-
// [params=(int) 1121202]
// SELECT t0.id FROM LSE1x1Lf t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1111202]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1111202]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? -FOR UPDATE WITH RR-
// [params=(int) 1111202]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121202]-
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:
@ -184,7 +195,12 @@ public class Test1x1LockScope extends LockScopeTestCase {
// FOR READ ONLY WITH RS USE AND KEEP UPDATE LOCKS [params=(String) firstName%1111201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1121201]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? [params=(int) 1111201]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: if jpa2, DO NOT lock LSE1x1RT using "FOR UPDATE OF col"
// SELECT t0.id, t0.version, t0.firstName, t1.id, t1.version, t1.lastName
@ -196,20 +212,23 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableRtName + Where + "\\(\\+\\).*"
+ ForUpdate);
break;
case derby: //TODO: **Non-atomic lock.
case derby: //-TODO: **Non-atomic lock.
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
// another transaction could modify the data before the lock is obtained.
// SELECT t0.id, t0.version, t0.firstName, t1.id, t1.version, t1.lastName FROM LSE1x1Lf t0
// LEFT OUTER JOIN LSE1x1Rt t1 ON t0.UNIRIGHT_ID = t1.id
// WHERE (t0.firstName LIKE ? ESCAPE '\') [params=(String) firstName%1111201]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1121201]
// SELECT t0.id FROM LSE1x1Lf t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1111201]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? [params=(int) 1111201]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121201]-
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:
@ -250,7 +269,12 @@ public class Test1x1LockScope extends LockScopeTestCase {
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(String) firstName%1111201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1121201]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? [params=(int) 1111201]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: if jpa2, DO NOT lock LSE1x1RT using "FOR UPDATE OF col"
// SELECT t0.id, t0.version, t0.firstName, t1.id, t1.version, t1.lastName
@ -262,20 +286,23 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableRtName + Where + "\\(\\+\\).*"
+ ForUpdate);
break;
case derby: //TODO: **Non-atomic lock.
case derby: //-TODO: **Non-atomic lock.
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
// another transaction could modify the data before the lock is obtained.
// SELECT t0.id, t0.version, t0.firstName, t1.id, t1.version, t1.lastName FROM LSE1x1Lf t0
// LEFT OUTER JOIN LSE1x1Rt t1 ON t0.UNIRIGHT_ID = t1.id
// WHERE (t0.firstName LIKE ? ESCAPE '\') [params=(String) firstName%1111201]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1121201]
// SELECT t0.id FROM LSE1x1Lf t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1111201]
// SELECT t0.version FROM LSE1x1Lf t0 WHERE t0.id = ? [params=(int) 1111201]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1121201]-
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:
@ -579,10 +606,18 @@ public class Test1x1LockScope extends LockScopeTestCase {
// SELECT t0.version, t0.firstName, t2.id, t2.version, t2.lastName FROM LSE1x1LfJT t0
// INNER JOIN Uni1x1LfJT_Uni1x1RT t1 ON t0.id = t1.LSE1X1LFJT_ID
// LEFT OUTER JOIN LSE1x1Rt t2 ON t1.UNIRIGHTJT_ID = t2.id WHERE t0.id = ?
// optimize for 1 row FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1112202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1122202]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1112202]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
// optimize for 1 row FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS
// [params=(int) 1112202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ?
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1122202]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ?
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(int) 1112202]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: If jpa2, DO NOT lock LSE1x1RT using "FOR UDPATE OF col"
// SELECT t0.version, t0.firstName, t2.id, t2.version, t2.lastName
@ -594,7 +629,7 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableJTName + Any + tableRtName + Where
+ "\\(\\+\\).*" + ForUpdate);
break;
case derby: //TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
case derby: //-TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
// DO NOT lock LSE1x1Rt
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
@ -603,13 +638,18 @@ public class Test1x1LockScope extends LockScopeTestCase {
// INNER JOIN Uni1x1LfJT_Uni1x1RT t1 ON t0.id = t1.LSE1X1LFJT_ID
// LEFT OUTER JOIN LSE1x1Rt t2 ON t1.UNIRIGHTJT_ID = t2.id WHERE t0.id = ?
// [params=(int) 1112202]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122202]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? -FOR UPDATE WITH RR-
// [params=(int) 1122202]
// SELECT t0.id FROM LSE1x1LfJT t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1112202]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1112202]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? -FOR UPDATE WITH RR-
// [params=(int) 1112202]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122202]-
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:
@ -627,7 +667,12 @@ public class Test1x1LockScope extends LockScopeTestCase {
// FOR READ ONLY WITH RS USE AND KEEP UPDATE LOCKS [params=(String) firstName%1112201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1122201]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? [params=(int) 1112201]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: If jpa2, DO NOT lock LSE1x1RT using "FOR UDPATE OF col"
// SELECT t0.id, t0.version, t0.firstName, t2.id, t2.version, t2.lastName
@ -639,7 +684,7 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableJTName + Any + tableRtName + Where
+ "\\(\\+\\).*" + ForUpdate);
break;
case derby: //TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
case derby: //-TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
// DO NOT lock LSE1x1Rt
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
@ -648,13 +693,16 @@ public class Test1x1LockScope extends LockScopeTestCase {
// INNER JOIN Uni1x1LfJT_Uni1x1RT t1 ON t0.id = t1.LSE1X1LFJT_ID
// LEFT OUTER JOIN LSE1x1Rt t2 ON t1.UNIRIGHTJT_ID = t2.id
// WHERE (t0.firstName LIKE ? ESCAPE '\') [params=(String) firstName%1112201]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1122201]
// SELECT t0.id FROM LSE1x1LfJT t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1112201]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? [params=(int) 1112201]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122201]-
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:
@ -699,7 +747,12 @@ public class Test1x1LockScope extends LockScopeTestCase {
// FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS [params=(String) firstName%1112201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1122201]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? [params=(int) 1112201]
assertLockTestSQLs(Select + joinTables + Where + DB2Lock);
assertLockTestSQLs(Select + joinTables + Where + DB2Lock,
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
case oracle: // TODO: If jpa2, DO NOT lock LSE1x1RT using "FOR UDPATE OF col"
// SELECT t0.id, t0.version, t0.firstName, t2.id, t2.version, t2.lastName
@ -711,7 +764,7 @@ public class Test1x1LockScope extends LockScopeTestCase {
assertLockTestSQLs(Select + tableLfName + Any + tableJTName + Any + tableRtName + Where
+ "\\(\\+\\).*" + ForUpdate);
break;
case derby: //TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
case derby: //-TODO: **Non-atomic lock, if jpa2/extended scope, LOCK Uni1x1LfJT_Uni1x1RT
// DO NOT lock LSE1x1Rt
// The database is unable to lock this query. Each object matching the query will be
// locked individually after it is loaded; however, it is technically possible that
@ -720,13 +773,16 @@ public class Test1x1LockScope extends LockScopeTestCase {
// INNER JOIN Uni1x1LfJT_Uni1x1RT t1 ON t0.id = t1.LSE1X1LFJT_ID
// LEFT OUTER JOIN LSE1x1Rt t2 ON t1.UNIRIGHTJT_ID = t2.id
// WHERE (t0.firstName LIKE ? ESCAPE '\') [params=(String) firstName%1112201]
// SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122201]
// SELECT t0.version FROM LSE1x1Rt t0 WHERE t0.id = ? [params=(int) 1122201]
// SELECT t0.id FROM LSE1x1LfJT t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1112201]
// SELECT t0.version FROM LSE1x1LfJT t0 WHERE t0.id = ? [params=(int) 1112201]
assertLockTestSQLs(Select + joinTables + Where + NoForUpdate,
Select + NoJoin + Any + tableLfName + Any + NoJoin + Where + ForUpdate,
Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
SelectVersion + NoJoin + Any + tableLfName + Any + NoJoin + Where + NoForUpdate,
SelectVersion + NoJoin + Any + tableRtName + Any + NoJoin + Where + NoForUpdate
);
//-SELECT t0.id FROM LSE1x1Rt t0 WHERE t0.id = ? FOR UPDATE WITH RR [params=(int) 1122201]
assertLockTestNoSQLs(Select + NoJoin + Any + tableRtName + Any + NoJoin + Where + ForUpdate
);
break;
default:

View File

@ -574,6 +574,7 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
}
if (waitTime < MinThreadWaitInMs / 2)
waitTime = MinThreadWaitInMs / 2;
log.trace(">> Started wait for " + waitTime + " ms");
if( waitThreadid != 0) {
thisThread.wait(waitTime);
} else {
@ -581,6 +582,7 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
wait(waitTime);
}
}
log.trace("<< Ended wait");
break;
case EmployeeNotNull:
@ -725,7 +727,7 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
new ArrayList<TestThread>(threads);
while (proceedThread.size() > 0
&& System.currentTimeMillis() < endTime) {
for (Thread thread : proceedThread) {
for (TestThread thread : proceedThread) {
if (thread.isAlive()) {
log.trace(thread + " is still alive, wait" +
" for 500ms and try again.");
@ -739,6 +741,9 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
continue;
} else {
deadThreads++;
if(thread.assertError != null){
throw thread.assertError;
}
proceedThread.remove(thread);
break;
}
@ -823,8 +828,8 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
logStack(ex);
} catch (Error err) {
// only remember the first exception caught
if (thisThread.throwable == null) {
thisThread.throwable = err;
if (thisThread.assertError == null) {
thisThread.assertError = err;
}
log.trace("Caught exception and continue: " + err);
logStack(err);
@ -852,11 +857,14 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
}
}
em.close();
Throwable firstThrowable = thisThread.throwable;
if (firstThrowable != null) {
if( firstThrowable instanceof Error )
throw (Error)firstThrowable;
if (thisThread.assertError != null) {
throw thisThread.assertError;
}
// Throwable firstThrowable = thisThread.throwable;
// if (firstThrowable != null) {
// if( firstThrowable instanceof Error )
// throw (Error)firstThrowable;
// }
log.trace("<<<< Sequenced Test: Threads=" + threadToRun + '/'
+ numThreads);
}
@ -927,6 +935,7 @@ public abstract class SequencedActionsTest extends SQLListenerTestCase {
private Map<Integer, LockEmployee> employees = null;
public Throwable throwable = null;
public Error assertError = null;
public boolean systemRolledback = false;
public TestThread(int threadToRun, Object[][]... actions) {

View File

@ -48,6 +48,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
/* ======== 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.PESSIMISTIC_WRITE, ExpectingAnyLockExClass);
@ -73,6 +74,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
{Act.WaitAllChildren},
{Act.TestException, 1, t1Exceptions},
{Act.RollbackTx}
};
Object[][] thread1 = {
{Act.CreateEm},
@ -81,6 +83,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
{Act.Flush},
{Act.Notify, 0},
{Act.Sleep, 1000},
{Act.FindWithLock, 1, t1Lock},
{Act.RollbackTx},
@ -90,10 +93,11 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
/* ======== 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.PESSIMISTIC_FORCE_INCREMENT,
// ExpectingAnyLockExClass);
}
private void commonNamedQueryTest( String testName,
@ -116,6 +120,8 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
{Act.WaitAllChildren},
{Act.TestException, 1, t1Exceptions},
{Act.RollbackTx}
};
Object[][] thread1 = {
{Act.CreateEm},
@ -124,6 +130,7 @@ public class TestMixedLockManagerDeadlock extends SequencedActionsTest {
{Act.Flush},
{Act.Notify, 0},
{Act.Sleep, 1000},
{Act.NamedQueryWithLock, "findEmployeeById", 1, t1Lock, "openjpa.hint.IgnorePreparedQuery", true},
{Act.RollbackTx},

View File

@ -38,7 +38,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(Read,Commit/Read,Commit)",
LockModeType.READ, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(Read,Commit/Read,Rollback)",
LockModeType.READ, Act.CommitTx, 1, null,
@ -49,8 +49,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(Read,Commit/Write,Commit)",
LockModeType.READ, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(Read,Commit/Write,Rollback)",
LockModeType.READ, Act.CommitTx, 1, null,
@ -95,7 +94,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(Write,Commit/Read,Commit)",
LockModeType.WRITE, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(Write,Commit/Read,Rollback)",
LockModeType.WRITE, Act.CommitTx, 1, null,
@ -106,8 +105,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(Write,Commit/Write,Commit)",
LockModeType.WRITE, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(Write,Commit/Write,Rollback)",
LockModeType.WRITE, Act.CommitTx, 1, null,
@ -139,8 +137,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
public void testFindWritePessimisticForceInc() {
commonFindTest(
"testFind(Write,Commit/PessimisticForceInc,Commit)",
LockModeType.WRITE, Act.CommitTx, 1,
ExpectingOptimisticLockExClass,
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null);
commonFindTest(
"testFind(Write,Commit/PessimisticForceInc,Rollback)",
@ -153,7 +150,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimisticRead,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimisticRead,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
@ -164,8 +161,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimisticRead,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimisticRead,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
@ -177,12 +173,10 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
"testFind(PessimisticRead,Commit/PessimisticRead,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 0, null);
// ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimisticRead,Commit/PessimisticRead,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 0, null);
// ExpectingOptimisticLockExClass);
}
public void testFindPessimisticReadPessimisticWrite() {
@ -212,7 +206,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimsiticWrite,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimsiticWrite,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
@ -223,8 +217,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimsiticWrite,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimsiticWrite,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
@ -269,7 +262,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimsiticForceInc,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimsiticForceInc,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
@ -280,8 +273,7 @@ public class TestMixedLockManagerFindPermutation extends SequencedActionsTest {
commonFindTest(
"testFind(PessimsiticForceInc,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonFindTest(
"testFind(PessimsiticForceInc,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,

View File

@ -38,7 +38,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(Read,Commit/Read,Commit)",
LockModeType.READ, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(Read,Commit/Read,Rollback)",
LockModeType.READ, Act.CommitTx, 1, null,
@ -49,8 +49,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(Read,Commit/Write,Commit)",
LockModeType.READ, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(Read,Commit/Write,Rollback)",
LockModeType.READ, Act.CommitTx, 1, null,
@ -95,7 +94,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(Write,Commit/Read,Commit)",
LockModeType.WRITE, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(Write,Commit/Read,Rollback)",
LockModeType.WRITE, Act.CommitTx, 1, null,
@ -106,8 +105,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(Write,Commit/Write,Commit)",
LockModeType.WRITE, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(Write,Commit/Write,Rollback)",
LockModeType.WRITE, Act.CommitTx, 1, null,
@ -139,8 +137,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
public void testLockWritePessimisticForceInc() {
commonLockTest(
"testLock(Write,Commit/PessimisticForceInc,Commit)",
LockModeType.WRITE, Act.CommitTx, 1,
ExpectingOptimisticLockExClass,
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null);
commonLockTest(
"testLock(Write,Commit/PessimisticForceInc,Rollback)",
@ -153,7 +150,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimisticRead,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimisticRead,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
@ -164,8 +161,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimisticRead,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimisticRead,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
@ -176,39 +172,33 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticRead,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticRead,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimisticReadPessimisticWrite() {
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticWrite,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticWrite,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimisticReadPessimisticForceInc() {
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticForceInc,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimisticRead,Commit/PessimisticForceInc,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
/* ======== Thread 1 : Pessimsitic Write Lock ============*/
@ -216,7 +206,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticWrite,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticWrite,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
@ -227,8 +217,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticWrite,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticWrite,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
@ -239,39 +228,33 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticRead,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticRead,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimsiticWritePessimisticWrite() {
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticWrite,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticWrite,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimsiticWritePessimisticForceInc() {
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticForceInc,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticWrite,Commit/PessimisticForceInc,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
/* ======== Thread 1 : Pessimsitic Force Increment Lock ============*/
@ -279,7 +262,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticForceInc,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticForceInc,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
@ -290,8 +273,7 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticForceInc,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticForceInc,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
@ -302,39 +284,33 @@ public class TestMixedLockManagerLockPermutation extends SequencedActionsTest {
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticRead,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticRead,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_READ, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimsiticForceIncPessimisticWrite() {
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticWrite,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticWrite,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_WRITE, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
public void testLockPessimsiticForceIncPessimisticForceInc() {
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticForceInc,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, ExpectingOptimisticLockExClass);
commonLockTest(
"testLock(PessimsiticForceInc,Commit/PessimisticForceInc,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 1, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1,
ExpectingOptimisticLockExClass);
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 1, ExpectingOptimisticLockExClass);
}
private void commonLockTest( String testName,

View File

@ -107,8 +107,7 @@ public class TestMixedLockManagerRefreshPermutation
commonRefreshTest(
"testRefresh(Write,Commit/Write,Commit)",
LockModeType.WRITE, Act.CommitTx, 2, null,
LockModeType.WRITE, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
commonRefreshTest(
"testRefresh(Write,Commit/Write,Rollback)",
LockModeType.WRITE, Act.CommitTx, 2, null,
@ -140,8 +139,7 @@ public class TestMixedLockManagerRefreshPermutation
public void testRefreshWritePessimisticForceInc() {
commonRefreshTest(
"testRefresh(Write,Commit/PessimisticForceInc,Commit)",
LockModeType.WRITE, Act.CommitTx, 2,
ExpectingOptimisticLockExClass,
LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null);
commonRefreshTest(
"testRefresh(Write,Commit/PessimisticForceInc,Rollback)",
@ -165,8 +163,7 @@ public class TestMixedLockManagerRefreshPermutation
commonRefreshTest(
"testRefresh(PessimisticRead,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
LockModeType.WRITE, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
commonRefreshTest(
"testRefresh(PessimisticRead,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_READ, Act.CommitTx, 2, null,
@ -206,7 +203,7 @@ public class TestMixedLockManagerRefreshPermutation
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
}
/* ======== Thread 1 : Pessimsitic Write Lock ============*/
/* ======== Thread 1 : Pessimistic Write Lock ============*/
public void testRefreshPessimsiticWriteRead() {
commonRefreshTest(
"testRefresh(PessimsiticWrite,Commit/Read,Commit)",
@ -222,8 +219,7 @@ public class TestMixedLockManagerRefreshPermutation
commonRefreshTest(
"testRefresh(PessimsiticWrite,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
LockModeType.WRITE, Act.CommitTx, 2,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
commonRefreshTest(
"testRefresh(PessimsiticWrite,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_WRITE, Act.CommitTx, 2, null,
@ -268,7 +264,7 @@ public class TestMixedLockManagerRefreshPermutation
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/Read,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
LockModeType.READ, Act.CommitTx, 0, ExpectingOptimisticLockExClass);
LockModeType.READ, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/Read,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
@ -279,8 +275,7 @@ public class TestMixedLockManagerRefreshPermutation
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/Write,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
LockModeType.WRITE, Act.CommitTx, 0,
ExpectingOptimisticLockExClass);
LockModeType.WRITE, Act.CommitTx, 2, ExpectingOptimisticLockExClass);
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/Write,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
@ -311,13 +306,11 @@ public class TestMixedLockManagerRefreshPermutation
public void testRefreshPessimsiticForceIncPessimisticForceInc() {
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/"
+ "PessimisticForceInc,Commit)",
"testRefresh(PessimsiticForceInc,Commit/PessimisticForceInc,Commit)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 3, null);
commonRefreshTest(
"testRefresh(PessimsiticForceInc,Commit/"
+ "PessimisticForceInc,Rollback)",
"testRefresh(PessimsiticForceInc,Commit/PessimisticForceInc,Rollback)",
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.CommitTx, 2, null,
LockModeType.PESSIMISTIC_FORCE_INCREMENT, Act.RollbackTx, 2, null);
}

View File

@ -28,6 +28,8 @@ import javax.persistence.PessimisticLockException;
import javax.persistence.Query;
import javax.persistence.QueryTimeoutException;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
/**
@ -35,9 +37,11 @@ import org.apache.openjpa.persistence.test.SQLListenerTestCase;
*/
public class TestPessimisticLocks extends SQLListenerTestCase {
private DBDictionary dict = null;
public void setUp() {
setSupportedDatabases(
// 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.DB2Dictionary.class);
if (isTestsDisabled()) {
@ -48,6 +52,8 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
String empTable = getMapping(Employee.class).getTable().getFullName();
String deptTable = getMapping(Department.class).getTable().getFullName();
dict= ((JDBCConfiguration)emf.getConfiguration()).getDBDictionaryInstance();
EntityManager em = null;
try {
em = emf.createEntityManager();
@ -96,25 +102,27 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
}
/*
* Test a find with pessimistic lock after a query with pessimistic lock and expect PessimisticLockException.
* Test find with pessimistic lock after a query with pessimistic lock.
*/
public void testFindWithLockTimeoutAfterQueryWithPessimisticLocks() {
public void testFindAfterQueryWithPessimisticLocks() {
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);
"select e from Employee e where e.id < 10").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<Employee> 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");
assertTrue("Test Employee first name = 'first.2'", q.get(0).getFirstName().equals("first.1")
|| q.get(0).getFirstName().equals("first.2"));
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// find Employee(2) with a lock, should block and expected a PessimisticLockException
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (QueryTimeoutException e) {
@ -135,23 +143,193 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
try {
em1.getTransaction().begin();
Query query = em1.createQuery(
"select e.department from Employee e where e.id < 10").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<Department> q = query.getResultList();
assertEquals("Expected 1 element with department id=20", q.size(), 1);
assertTrue("Test department name = 'D20'", q.get(0).getName().equals("D10")
|| q.get(0).getName().equals("D20"));
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// find Employee(2) with a lock, no block since only department was locked
Employee emp = em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
assertNotNull("Query locks department only, therefore should find Employee.", emp);
assertEquals("Test Employee first name = 'first.1'", emp.getFirstName(), "first.1");
} catch (QueryTimeoutException e) {
// TODO: DB2: This is the current unexpected exception due to OPENJPA-991.
// Remove this when the problem is fixed
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if( em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
em1.close();
em2.close();
}
/*
* Test find with pessimistic lock after a query with pessimistic lock.
*/
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<Employee> 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<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// find Employee(2) with a lock, should block and expected a PessimisticLockException
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (QueryTimeoutException e) {
// TODO: DB2: This is the current unexpected exception due to OPENJPA-991.
// Remove this when the problem is fixed
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if( em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
try {
em1.getTransaction().begin();
Query 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<Department> q = query.getResultList();
assertEquals("Expected 1 element with department id=20", q.size(), 1);
assertEquals("Test department name = 'D20'", q.get(0).getName(), "D20");
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// find Employee(2) with a lock, no block since only department was locked
Employee emp = em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
assertNotNull("Query locks department only, therefore should find Employee.", emp);
assertEquals("Test Employee first name = 'first.1'", emp.getFirstName(), "first.1");
} catch (QueryTimeoutException e) {
// TODO: DB2: This is the current unexpected exception due to OPENJPA-991.
// Remove this when the problem is fixed
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if( em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
em1.close();
em2.close();
}
/*
* Test query with pessimistic lock after a find with pessimistic lock.
*/
public void testQueryAfterFindWithPessimisticLocks() {
EntityManager em1 = emf.createEntityManager();
EntityManager em2 = emf.createEntityManager();
try {
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// Lock Emplyee(1), no department should be locked
em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
em1.getTransaction().begin();
Query query = em1.createQuery(
"select e.department from Employee e where e.id < 10").setFirstResult(1);
query.setLockMode(LockModeType.PESSIMISTIC_READ);
query.setHint("javax.persistence.query.timeout", 2000);
// Lock all selected Department but skip the first, i.e. lock Department(20), should query successfully.
List<Department> q = query.getResultList();
assertEquals("Expected 1 element with department id=20", q.size(), 1);
assertTrue("Test department name = 'D20'", q.get(0).getName().equals("D10")
|| q.get(0).getName().equals("D20"));
} catch (QueryTimeoutException e) {
// TODO: DB2: This is the current unexpected exception due to OPENJPA-991.
// Remove this when the problem is fixed
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if (em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
try {
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
Employee emp = em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
assertNotNull("Query locks department but find locks Employee.", emp);
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
// Lock Emplyee(2), no department should be locked
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
em1.getTransaction().begin();
Query query = em1.createQuery(
"select e from Employee e where e.id < 10").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<Employee> q = query.getResultList();
fail("Unexcpected find succeeded. Should throw a QueryLockException.");
} catch (QueryTimeoutException e) {
// TODO: This is the current unexpected exception due to OPENJPA-991. Remove this when the problem is fixed
// This is the expected exception.
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
@ -169,65 +347,71 @@ public class TestPessimisticLocks extends SQLListenerTestCase {
}
/*
* Test a query with pessimistic lock after a find with pessimistic lock and expect PessimisticLockException.
* Test query with pessimistic lock after a find with pessimistic lock.
*/
public void testQueryAfterFindWithPessimisticLocks() {
public void testQueryOrderByAfterFindWithPessimisticLocks() {
EntityManager em1 = emf.createEntityManager();
EntityManager em2 = emf.createEntityManager();
try {
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// Lock Emplyee(1), no department should be locked
em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
em1.getTransaction().begin();
Query query = em1.createQuery(
"select e.department from Employee e where e.id < 10 order by e.department.id").setFirstResult(1);
query.setLockMode(LockModeType.PESSIMISTIC_READ);
List<Department> q = query.getResultList();
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
} catch (PessimisticLockException e) {
// This is the expected exception.
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if (em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
em1.close();
em2.close();
}
/*
* Test a query with pessimistic lock with query timeout set after a find
* with pessimistic lock and expect QueryTimeoutException.
*/
public void testQueryWithQueryTimeoutAfterFindWithPessimisticLocks() {
EntityManager em1 = emf.createEntityManager();
EntityManager em2 = emf.createEntityManager();
try {
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
em2.find(Employee.class, 1, LockModeType.PESSIMISTIC_READ, map);
em1.getTransaction().begin();
Query query = em1.createQuery(
"select e.department from Employee e where e.id < 10 order by e.department.id").setFirstResult(1);
query.setLockMode(LockModeType.PESSIMISTIC_READ);
query.setHint("javax.persistence.query.timeout", 2000);
// Lock all selected Department but skip the first, i.e. lock Department(20), should query successfully.
List<Department> q = query.getResultList();
assertEquals("Expected 1 element with department id=20", q.size(), 1);
assertEquals("Test department name = 'D20'", q.get(0).getName(), "D20");
} catch (QueryTimeoutException e) {
// TODO: DB2: This is the current unexpected exception due to OPENJPA-991.
// Remove this when the problem is fixed
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
if( !(dict instanceof org.apache.openjpa.jdbc.sql.DB2Dictionary)) {
fail("Caught unexpected " + e.getClass().getName() + ":" + e.getMessage());
}
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {
if( em1.getTransaction().isActive())
em1.getTransaction().rollback();
if (em2.getTransaction().isActive())
em2.getTransaction().rollback();
}
fail("Unexcpected find succeeded. Should throw a PessimisticLockException.");
try {
em2.getTransaction().begin();
Map<String,Object> map = new HashMap<String,Object>();
map.put("javax.persistence.lock.timeout", 2000);
// Lock Emplyee(2), no department should be locked
em2.find(Employee.class, 2, LockModeType.PESSIMISTIC_READ, map);
em1.getTransaction().begin();
Query 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);
List<Employee> q = query.getResultList();
fail("Unexcpected find succeeded. Should throw a QueryLockException.");
} catch (QueryTimeoutException e) {
// This is the expected exception.
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
} catch (PessimisticLockException e) {
// TODO: This is the expected exception but will be fixed under OPENJPA-991
// System.out.println("Caught " + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception ex) {
fail("Caught unexpected " + ex.getClass().getName() + ":" + ex.getMessage());
} finally {