/***************************************************************** * 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.cayenne; import org.apache.cayenne.access.ToManyList; import org.apache.cayenne.configuration.server.ServerRuntime; import org.apache.cayenne.di.Inject; import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.test.jdbc.TableHelper; import org.apache.cayenne.testdo.testmap.ArtGroup; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.testdo.testmap.Gallery; import org.apache.cayenne.testdo.testmap.Painting; import org.apache.cayenne.testdo.testmap.PaintingInfo; import org.apache.cayenne.unit.di.server.CayenneProjects; import org.apache.cayenne.unit.di.server.ServerCase; import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.Before; import org.junit.Test; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class CayenneDataObjectRelationshipsIT extends ServerCase { @Inject private ObjectContext context; @Inject private ServerRuntime runtime; @Inject private DBHelper dbHelper; private TableHelper tArtist; private TableHelper tPaintingInfo; private TableHelper tPainting; @Before public void setUp() throws Exception { tArtist = new TableHelper(dbHelper, "ARTIST"); tArtist.setColumns("ARTIST_ID", "ARTIST_NAME"); tPainting = new TableHelper(dbHelper, "PAINTING"); tPainting.setColumns( "PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID"); tPaintingInfo = new TableHelper(dbHelper, "PAINTING_INFO"); tPaintingInfo.setColumns("PAINTING_ID", "TEXT_REVIEW"); } private void createArtistWithPaintingDataSet() throws Exception { tArtist.insert(8, "aX"); tPainting.insert(6, "pW", 8); } private void createArtistWithPaintingAndInfoDataSet() throws Exception { tArtist.insert(8, "aX"); tPainting.insert(6, "pW", 8); tPaintingInfo.insert(6, "mE"); } @Test public void testReadNestedProperty1() throws Exception { createArtistWithPaintingDataSet(); Painting p1 = Cayenne.objectForPK(context, Painting.class, 6); assertEquals("aX", p1.readNestedProperty("toArtist.artistName")); } @Test public void testReadNestedProperty2() throws Exception { createArtistWithPaintingDataSet(); Painting p1 = Cayenne.objectForPK(context, Painting.class, 6); assertTrue(p1.getToArtist().readNestedProperty("paintingArray") instanceof List<?>); } @Test public void testReciprocalRel1() throws Exception { createArtistWithPaintingDataSet(); Painting p1 = Cayenne.objectForPK(context, Painting.class, 6); Artist a1 = p1.getToArtist(); assertNotNull(a1); assertEquals("aX", a1.getArtistName()); List<Painting> paintings = a1.getPaintingArray(); assertEquals(1, paintings.size()); Painting p2 = paintings.get(0); assertSame(p1, p2); } @Test public void testReadToOneRel1() throws Exception { createArtistWithPaintingDataSet(); Painting p1 = Cayenne.objectForPK(context, Painting.class, 6); Artist a1 = p1.getToArtist(); assertNotNull(a1); assertEquals(PersistenceState.HOLLOW, a1.getPersistenceState()); assertEquals("aX", a1.getArtistName()); assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState()); } @Test public void testReadToOneRel2() throws Exception { // test chained calls to read relationships createArtistWithPaintingAndInfoDataSet(); PaintingInfo pi1 = Cayenne.objectForPK(context, PaintingInfo.class, 6); Painting p1 = pi1.getPainting(); p1.getPaintingTitle(); Artist a1 = p1.getToArtist(); assertNotNull(a1); assertEquals(PersistenceState.HOLLOW, a1.getPersistenceState()); assertEquals("aX", a1.getArtistName()); assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState()); } @Test public void testReadToOneRel3() throws Exception { createArtistWithPaintingDataSet(); Painting p1 = Cayenne.objectForPK(context, Painting.class, 6); Gallery g1 = p1.getToGallery(); assertNull(g1); } @Test public void testReadToManyRel1() throws Exception { createArtistWithPaintingDataSet(); Artist a1 = Cayenne.objectForPK(context, Artist.class, 8); List<Painting> plist = a1.getPaintingArray(); assertNotNull(plist); assertEquals(1, plist.size()); assertEquals(PersistenceState.COMMITTED, plist.get(0).getPersistenceState()); assertEquals("pW", plist.get(0).getPaintingTitle()); } @Test public void testReadToManyRel2() throws Exception { // test empty relationship tArtist.insert(11, "aX"); Artist a1 = Cayenne.objectForPK(context, Artist.class, 11); List<Painting> plist = a1.getPaintingArray(); assertNotNull(plist); assertEquals(0, plist.size()); } @Test public void testReflexiveRelationshipInsertOrder1() { ArtGroup parentGroup = context.newObject(ArtGroup.class); parentGroup.setName("parent"); ArtGroup childGroup1 = context.newObject(ArtGroup.class); childGroup1.setName("child1"); childGroup1.setToParentGroup(parentGroup); context.commitChanges(); childGroup1.setToParentGroup(null); context.commitChanges(); } @Test public void testReflexiveRelationshipInsertOrder2() { ArtGroup childGroup1 = context.newObject(ArtGroup.class); childGroup1.setName("child1"); ArtGroup parentGroup = context.newObject(ArtGroup.class); parentGroup.setName("parent"); childGroup1.setToParentGroup(parentGroup); context.commitChanges(); childGroup1.setToParentGroup(null); context.commitChanges(); } @Test public void testReflexiveRelationshipInsertOrder3() { // multiple children, one created before parent, one after ArtGroup childGroup1 = context.newObject(ArtGroup.class); childGroup1.setName("child1"); ArtGroup parentGroup = context.newObject(ArtGroup.class); parentGroup.setName("parent"); childGroup1.setToParentGroup(parentGroup); ArtGroup childGroup2 = context.newObject(ArtGroup.class); childGroup2.setName("child2"); childGroup2.setToParentGroup(parentGroup); context.commitChanges(); childGroup1.setToParentGroup(null); context.commitChanges(); childGroup2.setToParentGroup(null); context.commitChanges(); } @Test public void testReflexiveRelationshipInsertOrder4() { // multiple children, one created before parent, one after ArtGroup childGroup1 = context.newObject(ArtGroup.class); childGroup1.setName("child1"); ArtGroup parentGroup = context.newObject(ArtGroup.class); parentGroup.setName("parent"); childGroup1.setToParentGroup(parentGroup); ArtGroup childGroup2 = context.newObject(ArtGroup.class); childGroup2.setName("subchild"); childGroup2.setToParentGroup(childGroup1); context.commitChanges(); childGroup1.setToParentGroup(null); context.commitChanges(); childGroup2.setToParentGroup(null); context.commitChanges(); } @Test public void testCrossContextRelationshipException() { // Create this object in one context... Artist artist = context.newObject(Artist.class); // ...and this object in another context Painting painting = runtime.newContext().newObject(Painting.class); // Check setting a toOne relationship try { painting.setToArtist(artist); fail("Should have failed to set a cross-context relationship"); } catch (CayenneRuntimeException e) { // Fine.. it should throw an exception } assertNull(painting.getToArtist()); // Make sure it wasn't set // Now try the reverse (toMany) relationship try { artist.addToPaintingArray(painting); fail("Should have failed to add a cross-context relationship"); } catch (CayenneRuntimeException e) { // Fine.. it should throw an exception } assertEquals(0, artist.getPaintingArray().size()); } @Test public void testComplexInsertUpdateOrdering() { Artist artist = context.newObject(Artist.class); artist.setArtistName("a name"); context.commitChanges(); // Cause an update and an insert that need correct ordering Painting painting = context.newObject(Painting.class); painting.setPaintingTitle("a painting"); artist.addToPaintingArray(painting); context.commitChanges(); context.deleteObjects(artist); context.commitChanges(); } @Test public void testNewToMany() throws Exception { Artist artist = context.newObject(Artist.class); artist.setArtistName("test"); assertTrue(artist.readPropertyDirectly("paintingArray") instanceof ToManyList); ToManyList list = (ToManyList) artist.readPropertyDirectly("paintingArray"); assertFalse(list.isFault()); context.commitChanges(); assertFalse(list.isFault()); } }