diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/MixedLockManager.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/MixedLockManager.java index 9f31caa92..907c683b5 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/MixedLockManager.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/MixedLockManager.java @@ -83,7 +83,7 @@ public class MixedLockManager extends PessimisticLockManager { ClassMapping mapping = (ClassMapping) sm.getMetaData(); try { if (!mapping.getVersion().checkVersion(sm, this.getStore(), - true)) { + false)) { throw (new OptimisticException(_loc.get( "optimistic-violation-lock").getMessage())) .setFailedObject(sm.getObjectId()); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/LockEmployeeNonVersion.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/LockEmployeeNonVersion.java new file mode 100644 index 000000000..e64cd4b36 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/LockEmployeeNonVersion.java @@ -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); + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerNonVersion.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerNonVersion.java new file mode 100644 index 000000000..ee09162cd --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/lockmgr/TestMixedLockManagerNonVersion.java @@ -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()); + } +}