Package org.apache.cayenne.access

Source Code of org.apache.cayenne.access.JointPrefetchTest

/*****************************************************************
*   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 java.sql.Date;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.cayenne.DataObject;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.ObjectId;
import org.apache.cayenne.PersistenceState;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.ValueHolder;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.query.SortOrder;
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.unit.CayenneCase;

/**
* Tests joint prefetch handling by Cayenne access stack.
*/
public class JointPrefetchTest extends CayenneCase {

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        deleteTestData();
    }

    public void testJointPrefetchDataRows() throws Exception {
        createTestData("testJointPrefetch1");

        // query with to-many joint prefetches
        SelectQuery q = new SelectQuery(Painting.class);
        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
        q.setFetchingDataRows(true);
        q.addPrefetch(Painting.TO_ARTIST_PROPERTY).setSemantics(
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        DataContext context = createDataContext();

        List rows = context.performQuery(q);

        blockQueries();

        try {
            assertEquals(3, rows.size());

            // row should contain columns from both entities minus those duplicated in a
            // join...
            int rowWidth = getDbEntity("ARTIST").getAttributes().size()
                    + getDbEntity("PAINTING").getAttributes().size();
            Iterator it = rows.iterator();
            while (it.hasNext()) {
                DataRow row = (DataRow) it.next();
                assertEquals("" + row, rowWidth, row.size());

                // assert columns presence
                assertTrue(row + "", row.containsKey("PAINTING_ID"));
                assertTrue(row + "", row.containsKey("ARTIST_ID"));
                assertTrue(row + "", row.containsKey("GALLERY_ID"));
                assertTrue(row + "", row.containsKey("PAINTING_TITLE"));
                assertTrue(row + "", row.containsKey("ESTIMATED_PRICE"));
                assertTrue(row + "", row.containsKey("toArtist.ARTIST_NAME"));
                assertTrue(row + "", row.containsKey("toArtist.DATE_OF_BIRTH"));
            }
        }
        finally {
            unblockQueries();
        }
    }

    public void testJointPrefetchSQLTemplate() throws Exception {
        createTestData("testJointPrefetch1");

        // correctly naming columns is the key..
        SQLTemplate q = new SQLTemplate(
                Artist.class,
                "SELECT distinct "
                        + "#result('ESTIMATED_PRICE' 'BigDecimal' '' 'paintingArray.ESTIMATED_PRICE'), "
                        + "#result('PAINTING_TITLE' 'String' '' 'paintingArray.PAINTING_TITLE'), "
                        + "#result('GALLERY_ID' 'int' '' 'paintingArray.GALLERY_ID'), "
                        + "#result('PAINTING_ID' 'int' '' 'paintingArray.PAINTING_ID'), "
                        + "#result('ARTIST_NAME' 'String'), "
                        + "#result('DATE_OF_BIRTH' 'java.util.Date'), "
                        + "#result('t0.ARTIST_ID' 'int' '' 'ARTIST_ID') "
                        + "FROM ARTIST t0, PAINTING t1 "
                        + "WHERE t0.ARTIST_ID = t1.ARTIST_ID");

        PrefetchTreeNode prefetch = q.addPrefetch(Artist.PAINTING_ARRAY_PROPERTY);
        assertEquals(
                "Default semantics for SQLTemplate is assumed to be joint.",
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS,
                prefetch.getSemantics());
        q.setFetchingDataRows(false);

        DataContext context = createDataContext();

        List objects = context.performQuery(q);

        blockQueries();

        try {

            // without OUTER join we will get fewer objects...
            assertEquals(2, objects.size());

            Iterator it = objects.iterator();
            while (it.hasNext()) {
                Artist a = (Artist) it.next();
                List list = a.getPaintingArray();

                assertNotNull(list);
                assertFalse(((ValueHolder) list).isFault());
                assertTrue(list.size() > 0);

                Iterator children = list.iterator();
                while (children.hasNext()) {
                    Painting p = (Painting) children.next();
                    assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());

                    // make sure properties are not null..
                    assertNotNull(p.getPaintingTitle());
                }
            }
        }
        finally {
            unblockQueries();
        }
    }

    public void testJointPrefetchToOne() throws Exception {
        createTestData("testJointPrefetch1");

        // query with to-many joint prefetches
        SelectQuery q = new SelectQuery(Painting.class);
        q.addOrdering("db:PAINTING_ID", SortOrder.ASCENDING);
        q.addPrefetch(Painting.TO_ARTIST_PROPERTY).setSemantics(
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        DataContext context = createDataContext();

        List objects = context.performQuery(q);

        blockQueries();

        try {
            assertEquals(3, objects.size());

            Iterator it = objects.iterator();
            while (it.hasNext()) {
                Painting p = (Painting) it.next();
                Artist target = p.getToArtist();
                assertNotNull(target);
                assertEquals(PersistenceState.COMMITTED, target.getPersistenceState());
            }
        }
        finally {
            unblockQueries();
        }
    }

    /**
     * Tests that joined entities can have non-standard type mappings.
     */
    public void testJointPrefetchDataTypes() throws Exception {
        // prepare... can't load from XML, as it doesn't yet support dates..
        SQLTemplate artistSQL = new SQLTemplate(
                Artist.class,
                "insert into ARTIST (ARTIST_ID, ARTIST_NAME, DATE_OF_BIRTH) "
                        + "values (33001, 'a1', #bind($date 'DATE'))");
        artistSQL.setParameters(Collections.singletonMap("date", new Date(System
                .currentTimeMillis())));
        SQLTemplate paintingSQL = new SQLTemplate(
                Painting.class,
                "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) "
                        + "VALUES (33001, 'p1', 33001, 1000)");
        DataContext context = createDataContext();

        context.performNonSelectingQuery(artistSQL);
        context.performNonSelectingQuery(paintingSQL);

        // test
        SelectQuery q = new SelectQuery(Painting.class);
        q.addPrefetch(Painting.TO_ARTIST_PROPERTY).setSemantics(
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        ObjEntity artistE = getObjEntity("Artist");
        ObjAttribute dateOfBirth = (ObjAttribute) artistE.getAttribute("dateOfBirth");
        assertEquals("java.util.Date", dateOfBirth.getType());
        dateOfBirth.setType("java.sql.Date");
        try {
            List objects = context.performQuery(q);

            blockQueries();

            try {
                assertEquals(1, objects.size());

                Iterator it = objects.iterator();
                while (it.hasNext()) {
                    Painting p = (Painting) it.next();
                    Artist a = p.getToArtist();
                    assertNotNull(a);
                    assertNotNull(a.getDateOfBirth());
                    assertTrue(a.getDateOfBirth().getClass().getName(), Date.class
                            .isAssignableFrom(a.getDateOfBirth().getClass()));
                }
            }
            finally {
                unblockQueries();
            }
        }
        finally {
            dateOfBirth.setType("java.util.Date");
        }
    }

    public void testJointPrefetchToMany() throws Exception {
        createTestData("testJointPrefetch1");

        // query with to-many joint prefetches
        SelectQuery q = new SelectQuery(Artist.class);
        q.addPrefetch(Artist.PAINTING_ARRAY_PROPERTY).setSemantics(
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        DataContext context = createDataContext();

        List objects = context.performQuery(q);

        blockQueries();
        try {
            assertEquals(3, objects.size());

            Iterator it = objects.iterator();
            while (it.hasNext()) {
                Artist a = (Artist) it.next();
                List list = a.getPaintingArray();

                assertNotNull(list);
                assertFalse(((ValueHolder) list).isFault());

                Iterator children = list.iterator();
                while (children.hasNext()) {
                    Painting p = (Painting) children.next();
                    assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
                    // make sure properties are not null..
                    assertNotNull(p.getPaintingTitle());
                }
            }
        }
        finally {
            unblockQueries();
        }
    }

    public void testJointPrefetchToManyNonConflictingQualifier() throws Exception {
        createTestData("testJointPrefetch1");

        // query with to-many joint prefetches and qualifier that doesn't match
        // prefetch....
        Expression qualifier = ExpressionFactory.matchExp(
                Artist.ARTIST_NAME_PROPERTY,
                "artist1");
        SelectQuery q = new SelectQuery(Artist.class, qualifier);
        q.addPrefetch(Artist.PAINTING_ARRAY_PROPERTY).setSemantics(
                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        DataContext context = createDataContext();

        List objects = context.performQuery(q);

        blockQueries();

        try {

            assertEquals(1, objects.size());

            Artist a = (Artist) objects.get(0);
            List list = a.getPaintingArray();

            assertNotNull(list);
            assertFalse(((ValueHolder) list).isFault());
            assertEquals(2, list.size());

            Iterator children = list.iterator();
            while (children.hasNext()) {
                Painting p = (Painting) children.next();
                assertEquals(PersistenceState.COMMITTED, p.getPersistenceState());
                // make sure properties are not null..
                assertNotNull(p.getPaintingTitle());
            }

            // assert no duplicates
            Set s = new HashSet(list);
            assertEquals(s.size(), list.size());
        }
        finally {
            unblockQueries();
        }
    }

    public void testJointPrefetchMultiStep() throws Exception {
        createTestData("testJointPrefetch2");

        // query with to-many joint prefetches
        SelectQuery q = new SelectQuery(Artist.class);
        q
                .addPrefetch(
                        Artist.PAINTING_ARRAY_PROPERTY
                                + "."
                                + Painting.TO_GALLERY_PROPERTY)
                .setSemantics(PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);

        DataContext context = createDataContext();

        // make sure phantomly prefetched objects are not deallocated
        context.getObjectStore().objectMap = new HashMap<Object, Persistent>();

        // sanity check...
        DataObject g1 = (DataObject) context.getGraphManager().getNode(
                new ObjectId("Gallery", Gallery.GALLERY_ID_PK_COLUMN, 33001));
        assertNull(g1);

        List objects = context.performQuery(q);

        blockQueries();
        try {

            assertEquals(3, objects.size());

            Iterator it = objects.iterator();
            while (it.hasNext()) {
                Artist a = (Artist) it.next();
                ValueHolder list = (ValueHolder) a.getPaintingArray();

                assertNotNull(list);

                // intermediate relationship is not fetched...
                assertTrue(list.isFault());
            }

            // however both galleries must be in memory...
            g1 = (DataObject) context.getGraphManager().getNode(
                    new ObjectId("Gallery", Gallery.GALLERY_ID_PK_COLUMN, 33001));
            assertNotNull(g1);
            assertEquals(PersistenceState.COMMITTED, g1.getPersistenceState());
            DataObject g2 = (DataObject) context.getGraphManager().getNode(
                    new ObjectId("Gallery", Gallery.GALLERY_ID_PK_COLUMN, 33002));
            assertNotNull(g2);
            assertEquals(PersistenceState.COMMITTED, g2.getPersistenceState());
        }
        finally {
            unblockQueries();
        }
    }
}
TOP

Related Classes of org.apache.cayenne.access.JointPrefetchTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.