001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.persistence.kernel;
020:
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.Properties;
025: import java.util.TreeMap;
026:
027: import org.apache.openjpa.persistence.kernel.common.apps.AttachA;
028: import org.apache.openjpa.persistence.kernel.common.apps.AttachB;
029: import org.apache.openjpa.persistence.kernel.common.apps.AttachD;
030: import org.apache.openjpa.persistence.kernel.common.apps.AttachE;
031: import org.apache.openjpa.persistence.kernel.common.apps.DetachSMPC;
032:
033: import org.apache.openjpa.conf.OpenJPAConfiguration;
034: import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
035: import org.apache.openjpa.enhance.PCEnhancer;
036: import org.apache.openjpa.enhance.PersistenceCapable;
037: import org.apache.openjpa.kernel.DetachedStateManager;
038: import org.apache.openjpa.lib.util.Options;
039: import org.apache.openjpa.persistence.DetachStateType;
040: import org.apache.openjpa.persistence.OpenJPAEntityManager;
041: import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
042:
043: public class TestDetachedStateManager extends BaseKernelTest {
044:
045: private static boolean enhanced = false;
046:
047: private int oid;
048: private int doid;
049:
050: /**
051: * Creates a new instance of TestDetachedStateManager
052: */
053: public TestDetachedStateManager(String name) {
054: super (name);
055: }
056:
057: private void deleteAll() {
058: deleteAll(AttachA.class);
059: deleteAll(AttachD.class);
060: }
061:
062: public OpenJPAEntityManager getPM() {
063: OpenJPAEntityManager pm = super .getPM();
064: //FIXME jthomas
065: //pm.currentTransaction().setRestoreValues(false);
066: return pm;
067: }
068:
069: public void setUp() throws Exception {
070: super .setUp();
071:
072: deleteAll();
073:
074: OpenJPAEntityManager pm = getPM();
075: startTx(pm);
076: AttachB b = new AttachB();
077: pm.persist(b);
078: b.setAint(5);
079: b.setBstr("5");
080: b.getStringIntMap().put("5", new Integer(5));
081:
082: AttachE e = new AttachE();
083: e.setEstr("E");
084: e.setEint(5);
085:
086: AttachD d = new AttachD();
087: d.setDint(5);
088: d.setEmbeddedE(e);
089: b.getDs().add(d);
090:
091: pm.persist(d);
092:
093: oid = b.getId();
094: doid = d.getId();
095: endTx(pm);
096: endEm(pm);
097: }
098:
099: public void testDetach() {
100: OpenJPAEntityManager pm = getPM();
101: AttachB b = pm.find(AttachB.class, oid);
102:
103: assertNotNull("b is null in testDetach", b);
104:
105: b = (AttachB) pm.detach(b);
106: endEm(pm);
107:
108: assertTrue(pm.isDetached(b));
109: assertEquals(5, b.getAint());
110: assertEquals("5", b.getBstr());
111: assertNull(b.getStringIntMap());
112:
113: b.setAint(12);
114: b.setBstr("12");
115: TreeMap map = new TreeMap();
116: map.put("12", new Integer(12));
117: b.setStringIntMap(map);
118:
119: pm = getPM();
120: startTx(pm);
121: AttachB attached = (AttachB) pm.merge(b);
122: assertEquals(12, attached.getAint());
123: assertEquals("12", attached.getBstr());
124: assertNull(attached.getStringIntMap().get("12"));
125: assertEquals(new Integer(5), attached.getStringIntMap()
126: .get("5"));
127: endTx(pm);
128: endEm(pm);
129:
130: pm = getPM();
131: b = pm.find(AttachB.class, oid);
132: assertEquals(12, b.getAint());
133: assertEquals("12", b.getBstr());
134: assertNull(b.getStringIntMap().get("12"));
135: assertEquals(new Integer(5), b.getStringIntMap().get("5"));
136: endEm(pm);
137: }
138:
139: public void testDetachWithGroups() {
140: OpenJPAEntityManager pm = getPM();
141: //FIXME jthomas
142: // pm.getFetchPlan().setDetachmentOptions(FetchPlanImpl.DETACH_LOAD_FIELDS | FetchPlanImpl.DETACH_UNLOAD_FIELDS);
143: pm.setDetachState(DetachStateType.FETCH_GROUPS);
144: pm.getFetchPlan().addFetchGroup("all");
145: AttachB b = pm.find(AttachB.class, oid);
146:
147: assertNotNull("b is null in testDetachWithGroups", b);
148:
149: b = (AttachB) pm.detach(b);
150: endEm(pm);
151:
152: assertTrue(pm.isDetached(b));
153: assertEquals("b.getAint() not 5", 5, b.getAint());
154: assertEquals("b.getAint() not 5str", "5", b.getBstr());
155: assertEquals("b.getStringIntMap().size() not equal to 1", 1, b
156: .getStringIntMap().size());
157:
158: b.setAint(12);
159: b.setBstr("12");
160: b.getStringIntMap().put("12", new Integer(12));
161:
162: pm = getPM();
163: startTx(pm);
164: AttachB attached = (AttachB) pm.merge(b);
165: assertEquals("not 12", 12, attached.getAint());
166: assertEquals("not 12str", "12", attached.getBstr());
167: assertEquals("not newInteger(12)", new Integer(12), attached
168: .getStringIntMap().get("12"));
169: assertEquals("not newInteger(5)", new Integer(5), attached
170: .getStringIntMap().get("5"));
171: endTx(pm);
172: endEm(pm);
173:
174: pm = getPM();
175: b = (AttachB) pm.find(AttachB.class, oid);
176: assertEquals("not equal 12", 12, b.getAint());
177: assertEquals("not equal 12str", "12", b.getBstr());
178: assertEquals("not equal newinteger(12)", new Integer(12), b
179: .getStringIntMap().get("12"));
180: assertEquals("not equal newInteger(5)", new Integer(5), b
181: .getStringIntMap().get("5"));
182: endEm(pm);
183: }
184:
185: public void testDetachNoOverwrite() {
186: OpenJPAEntityManager pm = getPM();
187: AttachB b = (AttachB) pm.find(AttachB.class, oid);
188: b = (AttachB) pm.detach(b);
189: endEm(pm);
190:
191: b.setBstr("12");
192:
193: pm = getPM();
194: startTx(pm);
195: AttachB orig = pm.find(AttachB.class, oid);
196: orig.setAint(50);
197:
198: AttachB attached = (AttachB) pm.merge(b);
199: assertEquals(attached, orig);
200: assertEquals(50, attached.getAint());
201: assertEquals("12", attached.getBstr());
202: endTx(pm);
203: endEm(pm);
204:
205: pm = getPM();
206: b = (AttachB) pm.find(AttachB.class, oid);
207: assertEquals(50, b.getAint());
208: assertEquals("12", b.getBstr());
209: endEm(pm);
210: }
211:
212: public void testOptimisticLock() {
213: OpenJPAEntityManager pm = getPM();
214: AttachB b = (AttachB) pm.find(AttachB.class, oid);
215:
216: assertNotNull("b is null in testOptimisticLock", b);
217:
218: b = (AttachB) pm.detach(b);
219: endEm(pm);
220:
221: b.setAint(12);
222: b.setBstr("12");
223: TreeMap map = new TreeMap();
224: map.put("12", new Integer(12));
225: b.setStringIntMap(map);
226:
227: pm = getPM();
228: startTx(pm);
229: AttachB b2 = (AttachB) pm.find(AttachB.class, oid);
230: b2.setAint(15);
231: endTx(pm);
232: endEm(pm);
233:
234: pm = getPM();
235: startTx(pm);
236: try {
237: pm.merge(b);
238: endTx(pm);
239: fail("OL expected.");
240: } catch (Exception jove) {
241: rollbackTx(pm);
242: }
243: endEm(pm);
244: }
245:
246: public void testEmbedded() {
247: OpenJPAEntityManager pm = getPM();
248: AttachD d = pm.find(AttachD.class, doid);
249:
250: assertNotNull("d is null in testEmbedded", d);
251:
252: d.getEmbeddedE().getEstr();
253: d = (AttachD) pm.detach(d);
254: endEm(pm);
255:
256: d.getEmbeddedE().setEstr("E12");
257: pm = getPM();
258: startTx(pm);
259: AttachD d2 = (AttachD) pm.merge(d);
260: assertNotEquals(d.getEmbeddedE(), d2.getEmbeddedE());
261: assertEquals("E12", d2.getEmbeddedE().getEstr());
262: assertEquals(5, d2.getEmbeddedE().getEint());
263: endTx(pm);
264: endEm(pm);
265:
266: pm = getPM();
267: d2 = (AttachD) pm.find(AttachD.class, doid);
268:
269: assertNotNull("d2 is null in testEmbedded", d2);
270:
271: assertEquals("E12", d2.getEmbeddedE().getEstr());
272: assertEquals(5, d2.getEmbeddedE().getEint());
273: endEm(pm);
274: }
275:
276: public void testNullEmbedded() {
277: OpenJPAEntityManager pm = getPM();
278: AttachD d = (AttachD) pm.find(AttachD.class, doid);
279:
280: assertNotNull("d is null in testNullEmbedded", d);
281: d.getEmbeddedE().getEstr();
282: d = (AttachD) pm.detach(d);
283: endEm(pm);
284:
285: d.setEmbeddedE(null);
286: pm = getPM();
287: startTx(pm);
288: AttachD d2 = (AttachD) pm.merge(d);
289: assertNull(d2.getEmbeddedE());
290: endTx(pm);
291: endEm(pm);
292:
293: pm = getPM();
294: d2 = (AttachD) pm.find(AttachD.class, doid);
295:
296: assertNotNull("d2 is null in testNullEmbedded", d2);
297: // no null ind
298: if (d2.getEmbeddedE() != null) {
299: assertNull(d2.getEmbeddedE().getEstr());
300: assertEquals(0, d2.getEmbeddedE().getEint());
301: }
302: endEm(pm);
303: }
304:
305: public void testNullEmbeddedRelated() {
306: OpenJPAEntityManager pm = getPM();
307: AttachD d = (AttachD) pm.find(AttachD.class, doid);
308:
309: assertNotNull("d is null in testNullEmbeddedRelated", d);
310:
311: d.getEmbeddedE().getEstr();
312: d = (AttachD) pm.detach(d);
313: endEm(pm);
314:
315: d.getEmbeddedE().setEstr(null);
316: pm = getPM();
317: startTx(pm);
318: AttachD d2 = (AttachD) pm.merge(d);
319: assertNull("d2.getEmbeddedE().getEstr() is not null", d2
320: .getEmbeddedE().getEstr());
321: assertEquals("d2.getEmbeddedE().getEint() is not equal to 5",
322: 5, d2.getEmbeddedE().getEint());
323: endTx(pm);
324: endEm(pm);
325:
326: pm = getPM();
327: d2 = (AttachD) pm.find(AttachD.class, doid);
328: assertNull("d2.getEmbeddedE().getEstr() is not null", d2
329: .getEmbeddedE().getEstr());
330: assertEquals("d2.getEmbeddedE().getEint() is not 5", 5, d2
331: .getEmbeddedE().getEint());
332: endEm(pm);
333: }
334:
335: public void testNullCollection() {
336: OpenJPAEntityManager pm = getPM();
337: AttachB b = (AttachB) pm.find(AttachB.class, oid);
338: b.getDs();
339: b = (AttachB) pm.detach(b);
340: endEm(pm);
341:
342: assertEquals(1, b.getDs().size());
343: b.setDs(null);
344:
345: pm = getPM();
346: startTx(pm);
347: b = (AttachB) pm.merge(b);
348: assertNull(b.getDs());
349: endTx(pm);
350: endEm(pm);
351:
352: pm = getPM();
353: b = (AttachB) pm.find(AttachB.class, oid);
354: assertTrue(b.getDs() == null || b.getDs().size() == 0);
355: endEm(pm);
356: }
357:
358: public void testCollectionAdd() {
359: doCollectionTest(false);
360: }
361:
362: public void testCollectionChanges() {
363: doCollectionTest(true);
364: }
365:
366: private void doCollectionTest(boolean remove) {
367: OpenJPAEntityManager pm = getPM();
368: AttachB b = (AttachB) pm.find(AttachB.class, oid);
369:
370: assertNotNull("b is null in doCollectionTest", b);
371: b.getDs();
372: b = (AttachB) pm.detach(b);
373: endEm(pm);
374:
375: assertEquals("b is null in doCollectionTest", 1, b.getDs()
376: .size());
377: if (remove) {
378: for (Iterator it = b.getDs().iterator(); it.hasNext();) {
379: it.next();
380: it.remove();
381: }
382: }
383: AttachD d = new AttachD();
384: d.setDint(12);
385: b.getDs().add(d);
386:
387: pm = getPM();
388: startTx(pm);
389: b = (AttachB) pm.merge(b);
390: assertSize(remove ? 1 : 2, b.getDs());
391: endTx(pm);
392: endEm(pm);
393:
394: pm = getPM();
395: b = (AttachB) pm.find(AttachB.class, oid);
396: assertSize(remove ? 1 : 2, b.getDs());
397: boolean found1 = false;
398: boolean found2 = false;
399: for (Iterator it = b.getDs().iterator(); it.hasNext();) {
400: d = (AttachD) it.next();
401: switch (d.getDint()) {
402: case 5:
403: if (found1)
404: fail("Refound.");
405: found1 = true;
406: break;
407: case 12:
408: if (found2)
409: fail("Refound.");
410: found2 = true;
411: break;
412: default:
413: fail("Unknown d:" + d.getDint());
414: }
415: }
416:
417: if (remove)
418: assertFalse(found1);
419:
420: endEm(pm);
421: }
422:
423: /*
424: //###
425: // No time to get these working right now. Have to figure out how to
426: // enhance certain classes with different DetachState settings in autobuild.
427: public void testSerialization ()
428: throws Exception
429: {
430: doSerializationTest (false);
431: }
432:
433:
434: public void testSerializationAuto ()
435: throws Exception
436: {
437: doSerializationTest (true);
438: }
439: */
440:
441: private void doSerializationTest(boolean auto) throws Exception {
442: enhance();
443: Map props = new HashMap();
444: props.put("openjpa.DetachState", "DetachedStateField=true");
445:
446: OpenJPAEntityManagerFactory factory = (OpenJPAEntityManagerFactory) getEmf(props);
447: OpenJPAEntityManager pm = (OpenJPAEntityManager) factory
448: .createEntityManager();
449:
450: startTx(pm);
451: DetachSMPC pc = new DetachSMPC();
452: pc.setIntField(1);
453: DetachSMPC rel = new DetachSMPC();
454: rel.setIntField(2);
455: pc.getRelSet().add(rel);
456: pc.getStringIntMap().put("a", new Integer(99));
457: pm.persist(pc);
458: endTx(pm);
459: Object pcoid = pm.getObjectId(pc);
460: endEm(pm);
461:
462: pm = (OpenJPAEntityManager) factory.createEntityManager();
463: pc = (DetachSMPC) pm.find(DetachSMPC.class, pcoid);
464: pc.getRelSet();
465: pc.getStringIntMap();
466: if (!auto) {
467: pc = (DetachSMPC) pm.detach(pc);
468: assertDetachedSM(pc);
469: }
470: pc = (DetachSMPC) roundtrip(pc, false);
471: assertDetachedSM(pc);
472: endEm(pm);
473:
474: assertDetachedSM(pc);
475: assertSize(1, pc.getRelSet());
476: assertEquals(1, pc.getStringIntMap().size());
477:
478: pc.setIntField(3);
479: ((DetachSMPC) pc.getRelSet().iterator().next()).setIntField(4);
480: pc.getStringIntMap().put("b", new Integer(100));
481:
482: pc = (DetachSMPC) roundtrip(pc, false);
483:
484: assertDetachedSM(pc);
485: assertEquals(3, pc.getIntField());
486: assertSize(1, pc.getRelSet());
487: //assertDetachedSM (b.getDs ().iterator ().next ());
488: assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
489: .getIntField());
490: assertEquals(new Integer(100), pc.getStringIntMap().get("b"));
491:
492: pm = (OpenJPAEntityManager) factory.createEntityManager();
493: startTx(pm);
494: pc = (DetachSMPC) pm.merge(pc);
495: assertEquals(3, pc.getIntField());
496: assertSize(1, pc.getRelSet());
497: assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
498: .getIntField());
499: assertEquals(2, pc.getStringIntMap().size());
500: assertEquals(new Integer(100), pc.getStringIntMap().get("b"));
501: endTx(pm);
502: endEm(pm);
503:
504: pm = (OpenJPAEntityManager) factory.createEntityManager();
505: pc = (DetachSMPC) pm.find(DetachSMPC.class, pcoid);
506: assertEquals(3, pc.getIntField());
507: assertSize(1, pc.getRelSet());
508: assertEquals(4, ((DetachSMPC) pc.getRelSet().iterator().next())
509: .getIntField());
510: assertEquals(2, pc.getStringIntMap().size());
511: assertEquals(new Integer(100), pc.getStringIntMap().get("b"));
512:
513: startTx(pm);
514: deleteAll(DetachSMPC.class, pm);
515: endTx(pm);
516: endEm(pm);
517: factory.close();
518: }
519:
520: private void enhance() throws Exception {
521: Properties props = getProperties(new String[] {
522: "openjpa.DetachState", "DetachedStateField=true", });
523: OpenJPAConfiguration conf = new OpenJPAConfigurationImpl(true,
524: false);
525: conf.fromProperties(props);
526:
527: Options opts = new Options();
528: opts.put("jdo", "true");
529: PCEnhancer
530: .run(
531: conf,
532: new String[] { "org.apache.openjpa.persistence.kernel.noenhance.DetachSMPC" },
533: opts);
534: }
535:
536: private void assertDetachedSM(Object obj) {
537: OpenJPAEntityManager pm = getPM();
538: assertTrue(pm.isDetached(obj));
539: PersistenceCapable pc = (PersistenceCapable) obj;
540: assertEquals(DetachedStateManager.class, pc.pcGetStateManager()
541: .getClass());
542: endEm(pm);
543: }
544: }
|