mirror of https://github.com/apache/openjpa.git
OPENJPA-891 - Fix non-versioned entity locking support and add tests.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@783633 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
27b0abd46b
commit
edb329a475
|
@ -83,7 +83,7 @@ public class MixedLockManager extends PessimisticLockManager {
|
||||||
ClassMapping mapping = (ClassMapping) sm.getMetaData();
|
ClassMapping mapping = (ClassMapping) sm.getMetaData();
|
||||||
try {
|
try {
|
||||||
if (!mapping.getVersion().checkVersion(sm, this.getStore(),
|
if (!mapping.getVersion().checkVersion(sm, this.getStore(),
|
||||||
true)) {
|
false)) {
|
||||||
throw (new OptimisticException(_loc.get(
|
throw (new OptimisticException(_loc.get(
|
||||||
"optimistic-violation-lock").getMessage()))
|
"optimistic-violation-lock").getMessage()))
|
||||||
.setFailedObject(sm.getObjectId());
|
.setFailedObject(sm.getObjectId());
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.openjpa.persistence.lockmgr;
|
||||||
|
|
||||||
|
import java.io.Externalizable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInput;
|
||||||
|
import java.io.ObjectOutput;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class LockEmployeeNonVersion implements Externalizable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.getClass().getName() + '@'
|
||||||
|
+ Integer.toHexString(System.identityHashCode(this)) + "[id="
|
||||||
|
+ getId() + "] first=" + getFirstName()
|
||||||
|
+ ", last=" + getLastName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readExternal(ObjectInput in) throws IOException,
|
||||||
|
ClassNotFoundException {
|
||||||
|
id = in.readInt();
|
||||||
|
firstName = (String) in.readObject();
|
||||||
|
lastName = (String) in.readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeExternal(ObjectOutput out) throws IOException {
|
||||||
|
out.writeInt(id);
|
||||||
|
out.writeObject(firstName);
|
||||||
|
out.writeObject(lastName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.openjpa.persistence.lockmgr;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.LockModeType;
|
||||||
|
|
||||||
|
import org.apache.openjpa.lib.log.Log;
|
||||||
|
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test find, lock and refresh em methods against non-versioned entity.
|
||||||
|
*/
|
||||||
|
public class TestMixedLockManagerNonVersion extends SQLListenerTestCase {
|
||||||
|
|
||||||
|
private String empTableName;
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
setUp(LockEmployeeNonVersion.class
|
||||||
|
, "openjpa.LockManager", "mixed"
|
||||||
|
, "openjpa.Optimistic", "false"
|
||||||
|
);
|
||||||
|
commonSetUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test em.find(lockMode) on non-versioned entity.
|
||||||
|
*/
|
||||||
|
public void testFindNonVersionWithLock() {
|
||||||
|
commonFindNonVerWithLock(LockModeType.NONE);
|
||||||
|
commonFindNonVerWithLock(LockModeType.READ);
|
||||||
|
commonFindNonVerWithLock(LockModeType.WRITE);
|
||||||
|
commonFindNonVerWithLock(LockModeType.OPTIMISTIC);
|
||||||
|
commonFindNonVerWithLock(LockModeType.OPTIMISTIC_FORCE_INCREMENT);
|
||||||
|
commonFindNonVerWithLock(LockModeType.PESSIMISTIC_READ);
|
||||||
|
commonFindNonVerWithLock(LockModeType.PESSIMISTIC_WRITE);
|
||||||
|
commonFindNonVerWithLock(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void commonFindNonVerWithLock(LockModeType lockMode) {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
LockEmployeeNonVersion emp = em.find(LockEmployeeNonVersion.class, 1,
|
||||||
|
lockMode);
|
||||||
|
assertNotNull(emp);
|
||||||
|
String lastLastName = emp.getLastName();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lastLastName, emp.getLastName());
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 1, lockMode);
|
||||||
|
emp.setLastName(lockMode.toString());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lockMode.toString(), emp.getLastName());
|
||||||
|
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test em.lock(lockMode) on non-versioned entity.
|
||||||
|
*/
|
||||||
|
public void testLockNonVersionWithLock() {
|
||||||
|
commonLockNonVerWithLock(LockModeType.NONE);
|
||||||
|
commonLockNonVerWithLock(LockModeType.READ);
|
||||||
|
commonLockNonVerWithLock(LockModeType.WRITE);
|
||||||
|
commonLockNonVerWithLock(LockModeType.OPTIMISTIC);
|
||||||
|
commonLockNonVerWithLock(LockModeType.OPTIMISTIC_FORCE_INCREMENT);
|
||||||
|
commonLockNonVerWithLock(LockModeType.PESSIMISTIC_READ);
|
||||||
|
commonLockNonVerWithLock(LockModeType.PESSIMISTIC_WRITE);
|
||||||
|
commonLockNonVerWithLock(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void commonLockNonVerWithLock(LockModeType lockMode) {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
LockEmployeeNonVersion emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
em.lock(emp, lockMode);
|
||||||
|
String lastLastName = emp.getLastName();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lastLastName, emp.getLastName());
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 2);
|
||||||
|
em.lock(emp, lockMode);
|
||||||
|
emp.setLastName(lockMode.toString());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 2);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lockMode.toString(), emp.getLastName());
|
||||||
|
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test em.refresh(lockMode) on non-versioned entity.
|
||||||
|
*/
|
||||||
|
public void testRefreshNonVersionWithLock() {
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.NONE);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.READ);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.WRITE);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.OPTIMISTIC);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.OPTIMISTIC_FORCE_INCREMENT);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.PESSIMISTIC_READ);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.PESSIMISTIC_WRITE);
|
||||||
|
commonRefreshNonVerWithLock(LockModeType.PESSIMISTIC_FORCE_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void commonRefreshNonVerWithLock(LockModeType lockMode) {
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
LockEmployeeNonVersion emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
String lastLastName = emp.getLastName();
|
||||||
|
em.refresh(emp, lockMode);
|
||||||
|
assertEquals(lastLastName, emp.getLastName());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 1);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lastLastName, emp.getLastName());
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 3);
|
||||||
|
em.refresh(emp, lockMode);
|
||||||
|
emp.setLastName(lockMode.toString());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
emp = em.find(LockEmployeeNonVersion.class, 3);
|
||||||
|
assertNotNull(emp);
|
||||||
|
assertEquals(lockMode.toString(), emp.getLastName());
|
||||||
|
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void commonSetUp() {
|
||||||
|
empTableName = getMapping(LockEmployeeNonVersion.class).getTable()
|
||||||
|
.getFullName();
|
||||||
|
|
||||||
|
cleanupDB();
|
||||||
|
|
||||||
|
LockEmployeeNonVersion e1, e2, e3;
|
||||||
|
e1 = newEmployee(1);
|
||||||
|
e2 = newEmployee(2);
|
||||||
|
e3 = newEmployee(3);
|
||||||
|
|
||||||
|
resetSQL();
|
||||||
|
EntityManager em = null;
|
||||||
|
try {
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(e1);
|
||||||
|
em.persist(e2);
|
||||||
|
em.persist(e3);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
} finally {
|
||||||
|
if (em != null && em.isOpen()) {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertAllSQLInOrder("INSERT INTO " + empTableName + " .*");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanupDB() {
|
||||||
|
EntityManager em = null;
|
||||||
|
try {
|
||||||
|
em = emf.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
em.createQuery("delete from " + empTableName).executeUpdate();
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (em != null && em.isOpen()) {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LockEmployeeNonVersion newEmployee(int id) {
|
||||||
|
LockEmployeeNonVersion e = new LockEmployeeNonVersion();
|
||||||
|
e.setId(id);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Log getLog() {
|
||||||
|
return emf.getConfiguration().getLog("Tests");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Log getDumpStackLog() {
|
||||||
|
return emf.getConfiguration().getLog("DumpStack");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logStack(Throwable t) {
|
||||||
|
StringWriter str = new StringWriter();
|
||||||
|
PrintWriter print = new PrintWriter(str);
|
||||||
|
t.printStackTrace(print);
|
||||||
|
getDumpStackLog().trace(str.toString());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue