/*****************************************************************
* 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.access;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.ValueHolder;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.query.EJBQLQuery;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import org.apache.cayenne.testdo.testmap.Artist;
import org.apache.cayenne.testdo.testmap.ArtistExhibit;
import org.apache.cayenne.testdo.testmap.Exhibit;
import org.apache.cayenne.testdo.testmap.Gallery;
import org.apache.cayenne.testdo.testmap.Painting;
import org.apache.cayenne.unit.di.DataChannelInterceptor;
import org.apache.cayenne.unit.di.UnitTestClosure;
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.sql.Date;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
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.assertTrue;
@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
public class DataContextEJBQLFetchJoinIT extends ServerCase {
@Inject
protected ObjectContext context;
@Inject
protected DBHelper dbHelper;
@Inject
protected DataChannelInterceptor queryBlocker;
protected TableHelper tArtist;
protected TableHelper tPainting;
protected TableHelper tGallery;
protected TableHelper tExhibit;
protected TableHelper tArtistExhibit;
@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",
"ARTIST_ID",
"PAINTING_TITLE",
"ESTIMATED_PRICE").setColumnTypes(
Types.INTEGER,
Types.BIGINT,
Types.VARCHAR,
Types.DECIMAL);
tGallery = new TableHelper(dbHelper, "GALLERY");
tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
tExhibit = new TableHelper(dbHelper, "EXHIBIT");
tExhibit.setColumns("EXHIBIT_ID", "GALLERY_ID", "CLOSING_DATE", "OPENING_DATE");
tArtistExhibit = new TableHelper(dbHelper, "ARTIST_EXHIBIT");
tArtistExhibit.setColumns("ARTIST_ID", "EXHIBIT_ID");
}
protected void createOneFetchJoinDataSet() throws Exception {
tArtist.insert(1, "A1");
tArtist.insert(2, "A2");
tArtist.insert(3, "A3");
tPainting.insert(1, 1, "P11", 3000d);
tPainting.insert(2, 2, "P2", 5000d);
tPainting.insert(3, 1, "P12", 3000d);
}
protected void createMultipleFetchJoinsDataSet() throws Exception {
createOneFetchJoinDataSet();
tGallery.insert(1, "gallery1");
tGallery.insert(2, "gallery2");
long t = System.currentTimeMillis();
tExhibit.insert(1, 1, new Date(1 + 10000), new Date(t + 20000));
tExhibit.insert(2, 1, new Date(1 + 30000), new Date(t + 40000));
tArtistExhibit.insert(1, 1);
tArtistExhibit.insert(1, 2);
}
@Test
public void testFetchJoinForOneEntity() throws Exception {
createOneFetchJoinDataSet();
String ejbql = "SELECT a FROM Artist a JOIN FETCH a.paintingArray ";
EJBQLQuery query = new EJBQLQuery(ejbql);
final List<?> objects = context.performQuery(query);
queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
public void execute() {
assertEquals(2, objects.size());
Iterator<?> it = objects.iterator();
while (it.hasNext()) {
Artist a = (Artist) it.next();
List<Painting> list = a.getPaintingArray();
assertNotNull(list);
assertFalse(((ValueHolder) list).isFault());
for (Painting p : list) {
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
// make sure properties are not null..
assertNotNull(p.getPaintingTitle());
}
}
}
});
}
@Test
public void testSeveralFetchJoins() throws Exception {
createMultipleFetchJoinsDataSet();
String ejbql = "SELECT a "
+ "FROM Artist a JOIN FETCH a.paintingArray JOIN FETCH a.artistExhibitArray "
+ "WHERE a.artistName = 'A1'";
EJBQLQuery query = new EJBQLQuery(ejbql);
final List<?> objects = context.performQuery(query);
queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
public void execute() {
assertEquals(1, objects.size());
Artist a = (Artist) objects.get(0);
assertEquals("A1", a.getArtistName());
List<Painting> paintings = a.getPaintingArray();
assertNotNull(paintings);
assertFalse(((ValueHolder) paintings).isFault());
assertEquals(2, paintings.size());
List<String> expectedPaintingsNames = new ArrayList<String>();
expectedPaintingsNames.add("P11");
expectedPaintingsNames.add("P12");
Iterator<Painting> paintingsIterator = paintings.iterator();
while (paintingsIterator.hasNext()) {
Painting p = paintingsIterator.next();
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
assertNotNull(p.getPaintingTitle());
assertTrue(expectedPaintingsNames.contains(p.getPaintingTitle()));
}
List<ArtistExhibit> exibits = a.getArtistExhibitArray();
assertNotNull(exibits);
assertFalse(((ValueHolder) exibits).isFault());
assertEquals(2, exibits.size());
Iterator<ArtistExhibit> exibitsIterator = exibits.iterator();
while (exibitsIterator.hasNext()) {
ArtistExhibit ae = exibitsIterator.next();
assertEquals(PersistenceState.COMMITTED, ae.getPersistenceState());
assertNotNull(ae.getObjectId());
}
}
});
}
@Test
public void testSeveralEntitiesFetchJoins() throws Exception {
createMultipleFetchJoinsDataSet();
String ejbql = "SELECT DISTINCT a , g "
+ "FROM Artist a JOIN FETCH a.paintingArray , Gallery g JOIN FETCH g.exhibitArray "
+ "WHERE a.artistName='A1' AND g.galleryName='gallery1'";
EJBQLQuery query = new EJBQLQuery(ejbql);
final List<?> objects = context.performQuery(query);
queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
public void execute() {
assertNotNull(objects);
assertFalse(objects.isEmpty());
assertEquals(1, objects.size());
}
});
}
@Test
public void testSeveralEntitiesAndScalarFetchInnerJoins() throws Exception {
createMultipleFetchJoinsDataSet();
String ejbql = "SELECT DISTINCT a, a.artistName , g "
+ "FROM Artist a JOIN FETCH a.paintingArray, Gallery g JOIN FETCH g.exhibitArray "
+ "ORDER BY a.artistName";
EJBQLQuery query = new EJBQLQuery(ejbql);
final List<?> objects = context.performQuery(query);
queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
public void execute() {
assertEquals(2, objects.size());
Object[] firstRow = (Object[]) objects.get(0);
Artist a = (Artist) firstRow[0];
assertEquals("A1", a.getArtistName());
List<Painting> paintings = a.getPaintingArray();
assertNotNull(paintings);
assertFalse(((ValueHolder) paintings).isFault());
assertEquals(2, paintings.size());
List<String> expectedPaintingsNames = new ArrayList<String>();
expectedPaintingsNames.add("P11");
expectedPaintingsNames.add("P12");
Iterator<Painting> paintingsIterator = paintings.iterator();
while (paintingsIterator.hasNext()) {
Painting p = paintingsIterator.next();
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
assertNotNull(p.getPaintingTitle());
assertTrue(expectedPaintingsNames.contains(p.getPaintingTitle()));
}
String artistName = (String) firstRow[1];
assertEquals("A1", artistName);
Gallery g1 = (Gallery) firstRow[2];
assertEquals("gallery1", g1.getGalleryName());
List<Exhibit> exibits = g1.getExhibitArray();
assertNotNull(exibits);
assertFalse(((ValueHolder) exibits).isFault());
assertEquals(2, exibits.size());
Object[] secondRow = (Object[]) objects.get(1);
a = (Artist) secondRow[0];
assertEquals("A2", a.getArtistName());
paintings = a.getPaintingArray();
assertNotNull(paintings);
assertFalse(((ValueHolder) paintings).isFault());
assertEquals(1, paintings.size());
expectedPaintingsNames = new ArrayList<String>();
expectedPaintingsNames.add("P2");
paintingsIterator = paintings.iterator();
while (paintingsIterator.hasNext()) {
Painting p = paintingsIterator.next();
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
assertNotNull(p.getPaintingTitle());
assertTrue(expectedPaintingsNames.contains(p.getPaintingTitle()));
}
artistName = (String) secondRow[1];
assertEquals("A2", artistName);
Gallery g2 = (Gallery) secondRow[2];
assertEquals(g1, g2);
}
});
}
@Test
public void testSeveralEntitiesAndScalarFetchOuterJoins() throws Exception {
createMultipleFetchJoinsDataSet();
String ejbql = "SELECT DISTINCT a, a.artistName , g "
+ "FROM Artist a LEFT JOIN FETCH a.paintingArray, Gallery g LEFT JOIN FETCH g.exhibitArray "
+ "ORDER BY a.artistName, g.galleryName";
EJBQLQuery query = new EJBQLQuery(ejbql);
final List<?> objects = context.performQuery(query);
queryBlocker.runWithQueriesBlocked(new UnitTestClosure() {
public void execute() {
assertEquals(6, objects.size());
Object[] row = (Object[]) objects.get(0);
Artist a1 = (Artist) row[0];
assertEquals("A1", a1.getArtistName());
List<Painting> paintings = a1.getPaintingArray();
assertNotNull(paintings);
assertFalse(((ValueHolder) paintings).isFault());
assertEquals(2, paintings.size());
List<String> expectedPaintingsNames = new ArrayList<String>();
expectedPaintingsNames.add("P11");
expectedPaintingsNames.add("P12");
Iterator<Painting> paintingsIterator = paintings.iterator();
while (paintingsIterator.hasNext()) {
Painting p = paintingsIterator.next();
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
assertNotNull(p.getPaintingTitle());
assertTrue(expectedPaintingsNames.contains(p.getPaintingTitle()));
}
String artistName1 = (String) row[1];
assertEquals("A1", artistName1);
Gallery g1 = (Gallery) row[2];
assertEquals("gallery1", g1.getGalleryName());
List<?> exibits = g1.getExhibitArray();
assertNotNull(exibits);
assertFalse(((ValueHolder) exibits).isFault());
assertEquals(2, exibits.size());
row = (Object[]) objects.get(1);
assertEquals(a1, row[0]);
assertEquals(artistName1, row[1]);
Gallery g2 = (Gallery) row[2];
assertEquals("gallery2", g2.getGalleryName());
exibits = g2.getExhibitArray();
assertTrue(exibits.isEmpty());
row = (Object[]) objects.get(2);
Artist a2 = (Artist) row[0];
assertEquals("A2", a2.getArtistName());
paintings = a2.getPaintingArray();
assertNotNull(paintings);
assertEquals(1, paintings.size());
Painting p = paintings.get(0);
assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
assertNotNull(p.getPaintingTitle());
assertEquals("P2", p.getPaintingTitle());
String artistName2 = (String) row[1];
assertEquals("A2", artistName2);
assertEquals(g1, row[2]);
row = (Object[]) objects.get(3);
assertEquals(a2, row[0]);
assertEquals(artistName2, row[1]);
assertEquals(g2, row[2]);
row = (Object[]) objects.get(4);
Artist a3 = (Artist) row[0];
assertEquals("A3", a3.getArtistName());
paintings = a3.getPaintingArray();
assertTrue(paintings.isEmpty());
String artistName3 = (String) row[1];
assertEquals("A3", artistName3);
assertEquals(g1, row[2]);
row = (Object[]) objects.get(5);
assertEquals(a3, row[0]);
assertEquals(artistName3, row[1]);
assertEquals(g2, row[2]);
}
});
}
}