blob: 8e55226bb57153346ac7bebde9b1d6a79990ade1 [file] [log] [blame]
/*
* 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.jdbc.annotations;
import java.lang.reflect.Array;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.strats.MultiColumnVersionStrategy;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
/**
* Tests numeric version spanning multiple columns and those columns spanning
* multiple tables.
*
* @author Pinaki Poddar
*/
public class TestMultiColumnVersion extends SingleEMFTestCase {
public void setUp() {
setUp(MultiColumnVersionPC.class, MultiColumnSecondaryVersionPC.class,
CLEAR_TABLES);
}
public void testVersionStrategyIsSet() {
assertStrategy(MultiColumnVersionPC.class);
assertStrategy(MultiColumnSecondaryVersionPC.class);
}
public void assertStrategy(Class cls) {
ClassMapping mapping = getMapping(cls);
assertNotNull(mapping.getVersion());
assertTrue(mapping.getVersion().getStrategy()
instanceof MultiColumnVersionStrategy);
}
public void testVersionOnPersistAndUpdateForSingleTable() {
OpenJPAEntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MultiColumnVersionPC pc = new MultiColumnVersionPC();
assertEquals(null, em.getVersion(pc));
em.persist(pc);
em.getTransaction().commit();
assertVersionEquals(new Number[]{1,1, 1.0f}, em.getVersion(pc));
em.getTransaction().begin();
pc.setName("updated");
em.merge(pc);
em.getTransaction().commit();
assertVersionEquals(new Number[]{2,2, 2.0f}, em.getVersion(pc));
em.close();
}
public void testConcurrentOptimisticUpdateFailsForSingleTable() {
OpenJPAEntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
OpenJPAEntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
MultiColumnVersionPC pc1 = new MultiColumnVersionPC();
em1.persist(pc1);
em1.getTransaction().commit();
em1.getTransaction().begin();
Object oid = em1.getObjectId(pc1);
MultiColumnVersionPC pc2 = em2.find(MultiColumnVersionPC.class, oid);
assertVersionEquals(em1.getVersion(pc1), em2.getVersion(pc2));
pc1.setName("Updated in em1");
pc2.setName("Updated in em2");
em1.getTransaction().commit();
em1.close();
try {
em2.getTransaction().commit();
fail("Optimistic fail");
} catch (Exception e) {
} finally {
em2.close();
}
}
public void testConcurrentOptimisticReadSucceedsForSingleTable() {
OpenJPAEntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
OpenJPAEntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
MultiColumnVersionPC pc1 = new MultiColumnVersionPC();
em1.persist(pc1);
em1.getTransaction().commit();
em1.getTransaction().begin();
Object oid = em1.getObjectId(pc1);
MultiColumnVersionPC pc2 = em2.find(MultiColumnVersionPC.class, oid);
assertVersionEquals(em1.getVersion(pc1), em2.getVersion(pc2));
em1.getTransaction().commit();
em1.close();
em2.getTransaction().commit();
em2.close();
}
public void testVersionOnPersistAndUpdateForMultiTable() {
OpenJPAEntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MultiColumnSecondaryVersionPC pc = new MultiColumnSecondaryVersionPC();
assertEquals(null, em.getVersion(pc));
em.persist(pc);
em.getTransaction().commit();
assertVersionEquals(new Number[]{1,1,1,1}, em.getVersion(pc));
em.getTransaction().begin();
pc.setName("updated");
em.merge(pc);
em.getTransaction().commit();
assertVersionEquals(new Number[]{2,2,2,2}, em.getVersion(pc));
em.close();
}
public void testConcurrentOptimisticUpdateFailsForMultiTable() {
OpenJPAEntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
OpenJPAEntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
MultiColumnSecondaryVersionPC pc1 = new MultiColumnSecondaryVersionPC();
em1.persist(pc1);
em1.getTransaction().commit();
em1.getTransaction().begin();
Object oid = em1.getObjectId(pc1);
MultiColumnSecondaryVersionPC pc2 =
em2.find(MultiColumnSecondaryVersionPC.class, oid);
assertVersionEquals(em1.getVersion(pc1), em2.getVersion(pc2));
pc1.setName("Updated in em1");
pc2.setName("Updated in em2");
em1.getTransaction().commit();
em1.close();
try {
em2.getTransaction().commit();
fail("Optimistic fail");
} catch (Exception e) {
} finally {
em2.close();
}
}
public void testConcurrentOptimisticReadSucceedsForMultiTable() {
OpenJPAEntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
OpenJPAEntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
MultiColumnSecondaryVersionPC pc1 = new MultiColumnSecondaryVersionPC();
em1.persist(pc1);
em1.getTransaction().commit();
em1.getTransaction().begin();
Object oid = em1.getObjectId(pc1);
MultiColumnSecondaryVersionPC pc2 =
em2.find(MultiColumnSecondaryVersionPC.class, oid);
assertVersionEquals(em1.getVersion(pc1), em2.getVersion(pc2));
em1.getTransaction().commit();
em1.close();
em2.getTransaction().commit();
em2.close();
}
static void assertVersionEquals(Object expected, Object actual) {
assertTrue(expected.getClass().isArray());
assertTrue(actual.getClass().isArray());
assertEquals(Array.getLength(expected), Array.getLength(actual));
int n = Array.getLength(expected);
for (int i = 0; i < n; i++) {
Object v1 = Array.get(expected, i);
Object v2 = Array.get(actual, i);
// exact equality may fail on non-integral values
assertTrue("element " + i + " mismatch. Expeceted: " +
v1 + " actual: " + v2,
Math.abs(((Number)v1).doubleValue()
- ((Number)v2).doubleValue())
< 0.01);
}
}
}