blob: bb219e0a6428e97313a002ec03f411d681fc84db [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.kernel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.enhance.PCEnhancer;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.kernel.DetachedStateManager;
import org.apache.openjpa.lib.util.Options;
import org.apache.openjpa.persistence.DetachStateType;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
import org.apache.openjpa.persistence.kernel.common.apps.AttachA;
import org.apache.openjpa.persistence.kernel.common.apps.AttachB;
import org.apache.openjpa.persistence.kernel.common.apps.AttachD;
import org.apache.openjpa.persistence.kernel.common.apps.AttachE;
import org.apache.openjpa.persistence.kernel.common.apps.DetachSMPC;
public class TestDetachedStateManager extends BaseKernelTest {
private static boolean enhanced = false;
private int oid;
private int doid;
/**
* Creates a new instance of TestDetachedStateManager
*/
public TestDetachedStateManager(String name) {
super(name);
}
private void deleteAll() {
deleteAll(AttachA.class);
deleteAll(AttachD.class);
}
@Override
public OpenJPAEntityManager getPM() {
OpenJPAEntityManager pm = super.getPM();
//FIXME jthomas
//pm.currentTransaction().setRestoreValues(false);
return pm;
}
@Override
public void setUp() throws Exception {
super.setUp();
deleteAll();
OpenJPAEntityManager pm = getPM();
startTx(pm);
AttachB b = new AttachB();
pm.persist(b);
b.setAint(5);
b.setBstr("5");
b.getStringIntMap().put("5", 5);
AttachE e = new AttachE();
e.setEstr("E");
e.setEint(5);
AttachD d = new AttachD();
d.setDint(5);
d.setEmbeddedE(e);
b.getDs().add(d);
pm.persist(d);
oid = b.getId();
doid = d.getId();
endTx(pm);
endEm(pm);
}
public void testDetach() {
OpenJPAEntityManager pm = getPM();
AttachB b = pm.find(AttachB.class, oid);
assertNotNull("b is null in testDetach", b);
b = (AttachB) pm.detachCopy(b);
endEm(pm);
assertTrue(pm.isDetached(b));
assertEquals(5, b.getAint());
assertEquals("5", b.getBstr());
assertNull(b.getStringIntMap());
b.setAint(12);
b.setBstr("12");
TreeMap map = new TreeMap();
map.put("12", 12);
b.setStringIntMap(map);
pm = getPM();
startTx(pm);
AttachB attached = (AttachB) pm.merge(b);
assertEquals(12, attached.getAint());
assertEquals("12", attached.getBstr());
assertNull(attached.getStringIntMap().get("12"));
assertEquals(5, attached.getStringIntMap().get("5"));
endTx(pm);
endEm(pm);
pm = getPM();
b = pm.find(AttachB.class, oid);
assertEquals(12, b.getAint());
assertEquals("12", b.getBstr());
assertNull(b.getStringIntMap().get("12"));
assertEquals(5, b.getStringIntMap().get("5"));
endEm(pm);
}
public void testDetachWithGroups() {
OpenJPAEntityManager pm = getPM();
//FIXME jthomas
// pm.getFetchPlan().setDetachmentOptions(
// FetchPlanImpl.DETACH_LOAD_FIELDS | FetchPlanImpl.DETACH_UNLOAD_FIELDS);
pm.setDetachState(DetachStateType.FETCH_GROUPS);
pm.getFetchPlan().addFetchGroup("all");
AttachB b = pm.find(AttachB.class, oid);
assertNotNull("b is null in testDetachWithGroups", b);
b = (AttachB) pm.detachCopy(b);
endEm(pm);
assertTrue(pm.isDetached(b));
assertEquals("b.getAint() not 5", 5, b.getAint());
assertEquals("b.getAint() not 5str", "5", b.getBstr());
assertEquals("b.getStringIntMap().size() not equal to 1", 1,
b.getStringIntMap().size());
b.setAint(12);
b.setBstr("12");
b.getStringIntMap().put("12", 12);
pm = getPM();
startTx(pm);
AttachB attached = (AttachB) pm.merge(b);
assertEquals("not 12", 12, attached.getAint());
assertEquals("not 12str", "12", attached.getBstr());
assertEquals("not newInteger(12)", 12,
attached.getStringIntMap().get("12"));
assertEquals("not newInteger(5)", 5,
attached.getStringIntMap().get("5"));
endTx(pm);
endEm(pm);
pm = getPM();
b = (AttachB) pm.find(AttachB.class, oid);
assertEquals("not equal 12", 12, b.getAint());
assertEquals("not equal 12str", "12", b.getBstr());
assertEquals("not equal newinteger(12)", 12,
b.getStringIntMap().get("12"));
assertEquals("not equal newInteger(5)", 5,
b.getStringIntMap().get("5"));
endEm(pm);
}
public void testDetachNoOverwrite() {
OpenJPAEntityManager pm = getPM();
AttachB b = (AttachB) pm.find(AttachB.class, oid);
b = (AttachB) pm.detachCopy(b);
endEm(pm);
b.setBstr("12");
pm = getPM();
startTx(pm);
AttachB orig = pm.find(AttachB.class, oid);
orig.setAint(50);
AttachB attached = (AttachB) pm.merge(b);
assertEquals(attached, orig);
assertEquals(50, attached.getAint());
assertEquals("12", attached.getBstr());
endTx(pm);
endEm(pm);
pm = getPM();
b = (AttachB) pm.find(AttachB.class, oid);
assertEquals(50, b.getAint());
assertEquals("12", b.getBstr());
endEm(pm);
}
public void testOptimisticLock() {
OpenJPAEntityManager pm = getPM();
AttachB b = (AttachB) pm.find(AttachB.class, oid);
assertNotNull("b is null in testOptimisticLock", b);
b = (AttachB) pm.detachCopy(b);
endEm(pm);
b.setAint(12);
b.setBstr("12");
TreeMap map = new TreeMap();
map.put("12", 12);
b.setStringIntMap(map);
pm = getPM();
startTx(pm);
AttachB b2 = (AttachB) pm.find(AttachB.class, oid);
b2.setAint(15);
endTx(pm);
endEm(pm);
pm = getPM();
startTx(pm);
try {
pm.merge(b);
endTx(pm);
fail("OL expected.");
} catch (Exception jove) {
rollbackTx(pm);
}
endEm(pm);
}
public void testEmbedded() {
OpenJPAEntityManager pm = getPM();
AttachD d = pm.find(AttachD.class, doid);
assertNotNull("d is null in testEmbedded", d);
d.getEmbeddedE().getEstr();
d = (AttachD) pm.detachCopy(d);
endEm(pm);
d.getEmbeddedE().setEstr("E12");
pm = getPM();
startTx(pm);
AttachD d2 = (AttachD) pm.merge(d);
assertNotEquals(d.getEmbeddedE(), d2.getEmbeddedE());
assertEquals("E12", d2.getEmbeddedE().getEstr());
assertEquals(5, d2.getEmbeddedE().getEint());
endTx(pm);
endEm(pm);
pm = getPM();
d2 = (AttachD) pm.find(AttachD.class, doid);
assertNotNull("d2 is null in testEmbedded", d2);
assertEquals("E12", d2.getEmbeddedE().getEstr());
assertEquals(5, d2.getEmbeddedE().getEint());
endEm(pm);
}
public void testNullEmbedded() {
OpenJPAEntityManager pm = getPM();
AttachD d = (AttachD) pm.find(AttachD.class, doid);
assertNotNull("d is null in testNullEmbedded", d);
d.getEmbeddedE().getEstr();
d = (AttachD) pm.detachCopy(d);
endEm(pm);
d.setEmbeddedE(null);
pm = getPM();
startTx(pm);
AttachD d2 = (AttachD) pm.merge(d);
assertNull(d2.getEmbeddedE());
endTx(pm);
endEm(pm);
pm = getPM();
d2 = (AttachD) pm.find(AttachD.class, doid);
assertNotNull("d2 is null in testNullEmbedded", d2);
// no null ind
if (d2.getEmbeddedE() != null) {
assertNull(d2.getEmbeddedE().getEstr());
assertEquals(0, d2.getEmbeddedE().getEint());
}
endEm(pm);
}
public void testNullEmbeddedRelated() {
OpenJPAEntityManager pm = getPM();
AttachD d = (AttachD) pm.find(AttachD.class, doid);
assertNotNull("d is null in testNullEmbeddedRelated", d);
d.getEmbeddedE().getEstr();
d = (AttachD) pm.detachCopy(d);
endEm(pm);
d.getEmbeddedE().setEstr(null);
pm = getPM();
startTx(pm);
AttachD d2 = (AttachD) pm.merge(d);
assertNull("d2.getEmbeddedE().getEstr() is not null",
d2.getEmbeddedE().getEstr());
assertEquals("d2.getEmbeddedE().getEint() is not equal to 5", 5,
d2.getEmbeddedE().getEint());
endTx(pm);
endEm(pm);
pm = getPM();
d2 = (AttachD) pm.find(AttachD.class, doid);
assertNull("d2.getEmbeddedE().getEstr() is not null",
d2.getEmbeddedE().getEstr());
assertEquals("d2.getEmbeddedE().getEint() is not 5", 5,
d2.getEmbeddedE().getEint());
endEm(pm);
}
public void testNullCollection() {
OpenJPAEntityManager pm = getPM();
AttachB b = (AttachB) pm.find(AttachB.class, oid);
b.getDs();
b = (AttachB) pm.detachCopy(b);
endEm(pm);
assertEquals(1, b.getDs().size());
b.setDs(null);
pm = getPM();
startTx(pm);
b = (AttachB) pm.merge(b);
assertNull(b.getDs());
endTx(pm);
endEm(pm);
pm = getPM();
b = (AttachB) pm.find(AttachB.class, oid);
assertTrue(b.getDs() == null || b.getDs().size() == 0);
endEm(pm);
}
public void testCollectionAdd() {
doCollectionTest(false);
}
public void testCollectionChanges() {
doCollectionTest(true);
}
private void doCollectionTest(boolean remove) {
OpenJPAEntityManager pm = getPM();
AttachB b = (AttachB) pm.find(AttachB.class, oid);
assertNotNull("b is null in doCollectionTest", b);
b.getDs();
b = (AttachB) pm.detachCopy(b);
endEm(pm);
assertEquals("b is null in doCollectionTest", 1, b.getDs().size());
if (remove) {
for (Iterator it = b.getDs().iterator(); it.hasNext();) {
it.next();
it.remove();
}
}
AttachD d = new AttachD();
d.setDint(12);
b.getDs().add(d);
pm = getPM();
startTx(pm);
b = (AttachB) pm.merge(b);
assertSize(remove ? 1 : 2, b.getDs());
endTx(pm);
endEm(pm);
pm = getPM();
b = (AttachB) pm.find(AttachB.class, oid);
assertSize(remove ? 1 : 2, b.getDs());
boolean found1 = false;
boolean found2 = false;
for (Iterator it = b.getDs().iterator(); it.hasNext();) {
d = (AttachD) it.next();
switch (d.getDint()) {
case 5:
if (found1)
fail("Refound.");
found1 = true;
break;
case 12:
if (found2)
fail("Refound.");
found2 = true;
break;
default:
fail("Unknown d:" + d.getDint());
}
}
if (remove)
assertFalse(found1);
endEm(pm);
}
/*
//###
// No time to get these working right now. Have to figure out how to
// enhance certain classes with different DetachState settings in autobuild.
public void testSerialization ()
throws Exception
{
doSerializationTest (false);
}
public void testSerializationAuto ()
throws Exception
{
doSerializationTest (true);
}
*/
private void doSerializationTest(boolean auto) throws Exception {
enhance();
Map props = new HashMap();
props.put("openjpa.DetachState", "DetachedStateField=true");
OpenJPAEntityManagerFactory factory =
(OpenJPAEntityManagerFactory) getEmf(props);
OpenJPAEntityManager pm =
(OpenJPAEntityManager) factory.createEntityManager();
startTx(pm);
DetachSMPC pc = new DetachSMPC();
pc.setIntField(1);
DetachSMPC rel = new DetachSMPC();
rel.setIntField(2);
pc.getRelSet().add(rel);
pc.getStringIntMap().put("a", 99);
pm.persist(pc);
endTx(pm);
Object pcoid = pm.getObjectId(pc);
endEm(pm);
pm = (OpenJPAEntityManager) factory.createEntityManager();
pc = (DetachSMPC) pm.find(DetachSMPC.class, pcoid);
pc.getRelSet();
pc.getStringIntMap();
if (!auto) {
pc = (DetachSMPC) pm.detachCopy(pc);
assertDetachedSM(pc);
}
pc = (DetachSMPC) roundtrip(pc, false);
assertDetachedSM(pc);
endEm(pm);
assertDetachedSM(pc);
assertSize(1, pc.getRelSet());
assertEquals(1, pc.getStringIntMap().size());
pc.setIntField(3);
((DetachSMPC) pc.getRelSet().iterator().next()).setIntField(4);
pc.getStringIntMap().put("b", 100);
pc = (DetachSMPC) roundtrip(pc, false);
assertDetachedSM(pc);
assertEquals(3, pc.getIntField());
assertSize(1, pc.getRelSet());
//assertDetachedSM (b.getDs ().iterator ().next ());
assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
.getIntField());
assertEquals(100, pc.getStringIntMap().get("b"));
pm = (OpenJPAEntityManager) factory.createEntityManager();
startTx(pm);
pc = (DetachSMPC) pm.merge(pc);
assertEquals(3, pc.getIntField());
assertSize(1, pc.getRelSet());
assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
.getIntField());
assertEquals(2, pc.getStringIntMap().size());
assertEquals(100, pc.getStringIntMap().get("b"));
endTx(pm);
endEm(pm);
pm = (OpenJPAEntityManager) factory.createEntityManager();
pc = (DetachSMPC) pm.find(DetachSMPC.class, pcoid);
assertEquals(3, pc.getIntField());
assertSize(1, pc.getRelSet());
assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
.getIntField());
assertEquals(2, pc.getStringIntMap().size());
assertEquals(100, pc.getStringIntMap().get("b"));
startTx(pm);
deleteAll(DetachSMPC.class, pm);
endTx(pm);
endEm(pm);
factory.close();
}
private void enhance() throws Exception {
Properties props = getProperties(new String[]{
"openjpa.DetachState", "DetachedStateField=true",
});
OpenJPAConfiguration conf = new OpenJPAConfigurationImpl(true, false);
conf.fromProperties(props);
Options opts = new Options();
opts.put("jdo", "true");
PCEnhancer.run(conf, new String[]{
"org.apache.openjpa.persistence.kernel.noenhance.DetachSMPC" },
opts);
}
private void assertDetachedSM(Object obj) {
OpenJPAEntityManager pm = getPM();
assertTrue(pm.isDetached(obj));
PersistenceCapable pc = (PersistenceCapable) obj;
assertEquals(DetachedStateManager.class,
pc.pcGetStateManager().getClass());
endEm(pm);
}
}