Package org.apache.openjpa.persistence.jdbc.order

Source Code of org.apache.openjpa.persistence.jdbc.order.TestOrderColumn

/*
* 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.jdbc.order;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;

import javax.persistence.Query;

import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;

public class TestOrderColumn extends SingleEMFTestCase {  
   
    private Student[] students = new Student[12];
   
    public void setUp() {
        super.setUp(DROP_TABLES,
                Person.class, Player.class, BattingOrder.class,
                Trainer.class, Game.class, Inning.class,
                Course.class, Student.class,
                Owner.class, Bicycle.class, Car.class, Home.class,
                Widget.class,BiOrderMappedByEntity.class, BiOrderEntity.class );
        try {
            createQueryData();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /*
     * Verifies that a collection remains contiguous and element
     * indexes are reordered if an element is removed for a
     * OneToMany relationship
     */
    public void testOneToManyElementRemoval() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "batters",
            "batters_ORDER");// "batters_ORDER");

        // Create some data
        Player[] players = new Player[10];
        ArrayList<Player> playersArr = new ArrayList<Player>();
        em.getTransaction().begin();
        for (int i = 0; i < 10 ; i++) {
            players[i] = new Player("Player" + i, i+100);
            em.persist(players[i]);
            playersArr.add(players[i]);
        }
        em.getTransaction().commitAndResume();
                     
        // Persist the related entities
        BattingOrder order = new BattingOrder();
        order.setBatters(playersArr);
        em.persist(order);
        em.getTransaction().commit();
        em.refresh(order);
        em.clear();
       
        // Verify order is correct.
        BattingOrder newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        for (int i = 0; i < 10 ; i++) {
            assertEquals(newOrder.getBatters().get(i), (players[i]));
        }
       
        // Remove some items
        em.getTransaction().begin();
        newOrder.getBatters().remove(1);
        playersArr.remove(1);
        newOrder.getBatters().remove(5);
        playersArr.remove(5);       
        em.getTransaction().commit();
        em.clear();

        // Simple assertion via find
        newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        assertNotNull(newOrder.getBatters());
        assertEquals(playersArr.size(), newOrder.getBatters().size());
        for (int i = 0; i < playersArr.size() ; i++) {
              assertEquals(newOrder.getBatters().get(i), (playersArr.get(i)));
        }

        // Stronger assertion via INDEX value
        validateIndexAndValues(em, "BattingOrder", "batters", 0,
            playersArr.toArray(), "id",
            order.id);
       
        em.close();       
    }

    /*
     * Verifies that a collection remains contiguous and element
     * indexes are reordered if an element is removed for a
     * OneToMany relationship
     */
    public void testOneToManyBiDirElementRemoval() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Verify field name is the default via fm
        validateOrderColumnName(BiOrderMappedByEntity.class, "bo2mEntities",
            "bo2mEntities_ORDER");

        // Create some data
        BiOrderMappedByEntity bome = new BiOrderMappedByEntity();
        bome.setId(1);
        List<BiOrderEntity> boea = new ArrayList<BiOrderEntity>();
        for (int i = 0; i < 5; i++) {
            BiOrderEntity boe = new BiOrderEntity();
            boe.setId(i+1);
            boe.setName("Entity" + i);
            boe.setEntity(bome);
            boea.add(boe);
            bome.addBo2mEntity(boe);
        }

        // Persist
        em.getTransaction().begin();
        em.persist(bome);
        for (BiOrderEntity boe : boea) {
            em.persist(boe);
        }
        em.getTransaction().commit();       
        em.refresh(bome);
        em.clear();
       
        // Verify order is correct.
        BiOrderMappedByEntity newBome = em.find(BiOrderMappedByEntity.class,
            bome.getId());
        assertNotNull(newBome);
        for (int i = 0; i < 5 ; i++) {
            assertEquals(newBome.getBo2mEntities().get(i), boea.get(i));
        }
       
        // Remove an item
        em.getTransaction().begin();
        newBome.getBo2mEntities().get(2).setEntity(null);
        newBome.removeBo2mEntity(2);
        boea.remove(2);
        em.getTransaction().commit();
        em.clear();

        // Simple assertion via find
        newBome = em.find(BiOrderMappedByEntity.class, bome.getId());
        assertNotNull(newBome);
        assertNotNull(newBome.getBo2mEntities());
        assertEquals(boea.size(), newBome.getBo2mEntities().size());
        for (int i = 0; i < boea.size() ; i++) {
              assertEquals(newBome.getBo2mEntities().get(i), (boea.get(i)));
        }

        // Stronger assertion via INDEX value
        validateIndexAndValues(em, "BiOrderMappedByEntity", "bo2mEntities", 0,
            boea.toArray(), "id",
            bome.getId());
       
        em.close();
    }

    /*
     * Verifies that a collection remains contiguous and element
     * indexes are reordered if an element is removed for an
     * ElementCollection
     */
    public void testElementCollectionElementRemoval() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        Game game = new Game();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Game.class, "rainDates",
            "dateOrder");
       
        // Create a list of basic types
        java.sql.Date dates[] = new java.sql.Date[10];
        ArrayList<java.sql.Date> rainDates = new ArrayList<java.sql.Date>(10);
        Calendar today = Calendar.getInstance();
        for (int i = 0; i < 10; i++) {
            today.set(2009, 1, i+1);
            dates[i] = new java.sql.Date(today.getTimeInMillis());
        }
        // Add in reverse order
        for (int i = 9; i >= 0; i--) {
            rainDates.add(dates[i]);
        }
        game.setRainDates(rainDates);
       
        em.getTransaction().begin();
        em.persist(game);
        em.getTransaction().commit();
              
        em.clear();
       
        Game newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        // Verify the order
        for (int i = 0; i < 10; i++) {
            assertEquals(game.getRainDates().get(i),
                rainDates.get(i));
        }
       
        // Remove some dates
        em.getTransaction().begin();
        newGame.getRainDates().remove(4);
        rainDates.remove(4);
        newGame.getRainDates().remove(2);
        rainDates.remove(2);
        em.getTransaction().commit();
        em.clear();

        newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        assertNotNull(newGame.getRainDates());
        assertEquals(8, newGame.getRainDates().size());
        // Verify the order
        for (int i = 0; i < newGame.getRainDates().size(); i++) {
            assertEquals(newGame.getRainDates().get(i).toString(),
                rainDates.get(i).toString());
        }
       
        // Stronger assertion via INDEX value
        validateCollIndexAndValues(em, "Game", "rainDates", 0,
            newGame.getRainDates().toArray(), "id",
            newGame.getId());
       
        em.close();
    }
    /*
     * Verifies that a collection remains contiguous and element
     * indexes are reordered if an element is inserted into the collection.
     */
    public void testOneToManyElementInsert() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "batters",
            "batters_ORDER");// "batters_ORDER");

        // Create some data
        Player[] players = new Player[10];
        ArrayList<Player> playersArr = new ArrayList<Player>();
        em.getTransaction().begin();
        for (int i = 0; i < 10 ; i++) {
            players[i] = new Player("Player" + i, i+100);
            em.persist(players[i]);
            playersArr.add(players[i]);
        }
        em.getTransaction().commitAndResume();
                     
        // Persist the related entities
        BattingOrder order = new BattingOrder();
        order.setBatters(playersArr);
        em.persist(order);
        em.getTransaction().commitAndResume();
        em.refresh(order);
       
        em.getTransaction().commit();
        em.clear();
       
        // Verify order is correct.
        BattingOrder newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        for (int i = 0; i < 10 ; i++) {
            assertEquals(newOrder.getBatters().get(i), (players[i]));
        }
               
        Player p = new Player("PlayerNew", 150);
        playersArr.add(2, p);

        Player p2 = new Player("PlayerNew2", 151);
        playersArr.add(p2);
        // Add an item at index 2 and at the end of the list
        em.getTransaction().begin();
        newOrder.getBatters().add(2, p);
        newOrder.getBatters().add(p2);
        em.getTransaction().commit();
        em.clear();

        // Simple assertion via find
        newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        assertNotNull(newOrder.getBatters());
        assertEquals(playersArr.size(), newOrder.getBatters().size());
        for (int i = 0; i < playersArr.size() ; i++) {
              assertEquals(newOrder.getBatters().get(i), (playersArr.get(i)));
        }

        // Stronger assertion via INDEX value
        validateIndexAndValues(em, "BattingOrder", "batters", 0,
            playersArr.toArray(), "id",
            order.id);
       
        em.close();       
    }
    /*
     * Verifies that a collection remains contiguous and element
     * indexes are reordered if an element is inserted into an
     * ElementCollection
     */
    public void testElementCollectionElementInsert() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        Game game = new Game();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Game.class, "rainDates",
            "dateOrder");
       
        // Create a list of basic types
        java.sql.Date dates[] = new java.sql.Date[10];
        ArrayList<java.sql.Date> rainDates = new ArrayList<java.sql.Date>(10);
        Calendar today = Calendar.getInstance();
        for (int i = 0; i < 10; i++) {
            today.set(2009, 1, i+1);
            dates[i] = new java.sql.Date(today.getTimeInMillis());
        }
        // Add in reverse order
        for (int i = 9; i >= 0; i--) {
            rainDates.add(dates[i]);
        }
        game.setRainDates(rainDates);
       
        em.getTransaction().begin();
        em.persist(game);
        em.getTransaction().commit();
              
        em.clear();
       
        Game newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        // Verify the order
        for (int i = 0; i < 10; i++) {
            assertEquals(game.getRainDates().get(i),
                rainDates.get(i));
        }
       
        // Add some dates
        today.set(2009, 1, 15);
        rainDates.add(1, new java.sql.Date(today.getTimeInMillis()));
        today.set(2009, 1, 20);
        rainDates.add(6, new java.sql.Date(today.getTimeInMillis()));
       
        em.getTransaction().begin();
        game.getRainDates().add(1, rainDates.get(1));
        game.getRainDates().add(6, rainDates.get(6));
        em.getTransaction().commit();
        em.clear();

        newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        assertNotNull(game.getRainDates());
        assertEquals(12, game.getRainDates().size());
        // Verify the order
        for (int i = 0; i < game.getRainDates().size(); i++) {
            assertEquals(game.getRainDates().get(i),
                rainDates.get(i));
        }
       
        em.close();
    }

   
    /*
     * Validates use of OrderColumn with OneToMany using the default
     * order column name
     */
    public void testOneToManyDefault() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "batters",
            "batters_ORDER");// "batters_ORDER");

        // Create some data
        Player[] players = new Player[10];
        em.getTransaction().begin();
        for (int i = 0; i < 10 ; i++) {
            players[i] = new Player("Player" + i, i);
            em.persist(players[i]);
        }
        em.getTransaction().commitAndResume();
       
       
        // Add it to the persistent list in reverse order
        ArrayList<Player> playersArr = new ArrayList<Player>();
        for (int i = 0; i < 10 ; i++) {
            playersArr.add(players[9 - i]);
        }
       
        // Persist the related entities
        BattingOrder order = new BattingOrder();
        order.setBatters(playersArr);
        em.persist(order);
        em.getTransaction().commit();
        em.refresh(order);
        em.clear();
       
        // Verify order is correct.
        BattingOrder newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        for (int i = 0; i < 10 ; i++) {
            assertEquals(newOrder.getBatters().get(i), (players[9 - i]));
        }
       
        // Add another entity and check order
        Player newPlayer = new Player("New Player", 99);
       
        em.getTransaction().begin();
        newOrder.getBatters().add(9, newPlayer);
        em.getTransaction().commit();
        em.clear();

        newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        for (int i = 0; i <= 10 ; i++) {
            if (i < 9)
              assertEquals(newOrder.getBatters().get(i), (players[9 - i]));
            else if (i == 9)
              assertEquals(newOrder.getBatters().get(i), newPlayer);
            else if (i == 10)
              assertEquals(newOrder.getBatters().get(i), players[0]);
        }
       
        em.close();
    }

    /*
     * Validates use of OrderColumn with OneToMany using a specified
     * order column name
     */
    public void testOneToManyNamed() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
       
        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "pinch_hitters",
            "pinch_order");

        // Create some data
        Player[] players = new Player[4];
        em.getTransaction().begin();
        for (int i = 0; i < 4 ; i++) {
            players[i] = new Player("PinchHitter" + i, i);
            em.persist(players[i]);
        }
        em.getTransaction().commitAndResume();
               
        // Add it to the persistent list in reverse order
        ArrayList<Player> pinchArr = new ArrayList<Player>();
        for (int i = 0; i < players.length ; i++) {
            pinchArr.add(players[players.length - 1 - i]);
        }
       
        // Persist the related entities
        BattingOrder order = new BattingOrder();
        order.setPinchHitters(pinchArr);
        em.persist(order);
        em.getTransaction().commit();       
        em.clear();
       
        // Verify order is correct.
        BattingOrder newOrder = em.find(BattingOrder.class, order.id);
        assertNotNull(newOrder);
        for (int i = 0; i < players.length ; i++) {
            assertEquals(newOrder.getPinchHitters().get(i),
                    (players[players.length - 1 - i]));
        }
        em.close();
    }

    /*
     * Validates use of OrderColumn with ManyToMany relationship
     */
    public void testManyToMany() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Trainer.class, "playersTrained",
            "trainingOrder");
       
        // Create some data
        Player[] players = new Player[25];
        em.getTransaction().begin();
        for (int i = 0; i < players.length ; i++) {
            players[i] = new Player("TrainedPlayer" + i, i);
            em.persist(players[i]);
        }
        em.getTransaction().commitAndResume();

        // Create M2M, add players in reverse insert order to
        // validate column order
        Trainer[] trainers = new Trainer[5];
        for (int i = 0; i < trainers.length; i++) {
            trainers[i] = new Trainer("Trainer" + i);
            ArrayList<Player> trained = new ArrayList<Player>();
            for (int j = ((i * 5) + 4); j >= (i * 5); j--) {
                trained.add(players[j]);
                if (players[j].getTrainers() == null)
                    players[j].setTrainers(new ArrayList<Trainer>());
                players[j].getTrainers().add(trainers[i]);
            }
            trainers[i].setPlayersTrained(trained);
            em.persist(trainers[i]);
        }
        em.getTransaction().commit();
       
        em.clear();
        // Verify order is correct.
        for (int i = 0; i < trainers.length; i++) {
            Trainer trainer = em.find(Trainer.class, trainers[i].getId());
            assertNotNull(trainer);
            List<Player> trainedPlayers = trainer.getPlayersTrained();
            assertNotNull(trainedPlayers);
            assertEquals(trainedPlayers.size(), 5);
            for (int j = trainedPlayers.size() - 1; j >=; j--) {
                assertEquals(trainedPlayers.get(j),
                    (players[(i * 5) + (4 - j)]));
            }
        }
        em.close();
    }

    /*
     * Validates use of OrderColumn with ManyToMany bi-directional with
     * both sides of the relationship maintaining order.  This test is not
     * currently run since work is underway to determine the feasiblity of
     * bi-directional ordering. 
     */
    public void validateBiOrderedManyToMany() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Game.class, "playedIn",
            "playerOrder");

        validateOrderColumnName(Player.class, "gamesPlayedIn",
            "playedInOrder");

        // Create some data
        Player[] players = new Player[25];
        em.getTransaction().begin();
        for (int i = 0; i < players.length ; i++) {
            players[i] = new Player("GamePlayer" + i, i);
            em.persist(players[i]);
        }
        em.getTransaction().commitAndResume();

        // Create M2M, add players in reverse insert order to
        // validate column order
        Game[] games = new Game[5];
        for (int i = 0; i < games.length; i++) {
            games[i] = new Game();
            ArrayList<Player> playedIn = new ArrayList<Player>();
            for (int j = ((i * 5) + 4); j >= (i * 5); j--) {
                playedIn.add(players[j]);
                if (players[j].getGamesPlayedIn() == null)
                    players[j].setGamesPlayedIn(new ArrayList<Game>());
                players[j].getGamesPlayedIn().add(games[i]);
            }
            games[i].setPlayedIn(playedIn);
            em.persist(games[i]);
        }
        em.getTransaction().commit();
       
        em.clear();
        // Verify order is correct.
        for (int i = 0; i < games.length; i++) {
            Game game = em.find(Game.class, games[i].getId());
            assertNotNull(game);
            List<Player> playedIn = game.getPlayedIn();
            assertNotNull(playedIn);
            assertEquals(playedIn.size(), 5);
            for (int j = playedIn.size() - 1; j >=; j--) {
                Player p = playedIn.get(j);
                assertEquals(p,
                    (players[(i * 5) + (4 - j)]));
                for (int k = 0; k < p.getGamesPlayedIn().size(); k++) {
                    assertNotNull(p.getGamesPlayedIn());
                    assertEquals(p.getGamesPlayedIn().get(k),
                            games[k]);
                }
            }           
        }
        em.close();       
    }

    /*
     * Validates use of OrderColumn with ElementCollection of basic
     * elements
     */
    public void testElementCollectionBasic() {
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        Game game = new Game();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Game.class, "rainDates",
            "dateOrder");
       
        // Create a list of basic types
        java.sql.Date dates[] = new java.sql.Date[10];
        ArrayList<java.sql.Date> rainDates = new ArrayList<java.sql.Date>(10);
        Calendar today = Calendar.getInstance();
        for (int i = 0; i < 10; i++) {
            today.set(2009, 1, i+1);
            dates[i] = new java.sql.Date(today.getTimeInMillis());
        }
        // Add in reverse order
        for (int i = 9; i >= 0; i--) {
            rainDates.add(dates[i]);
        }
        game.setRainDates(rainDates);
       
        em.getTransaction().begin();
        em.persist(game);
        em.getTransaction().commit();

        em.clear();
       
        Game newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        // Verify the order
        for (int i = 0; i < 10; i++) {
            assertEquals(game.getRainDates().get(i),
                dates[9-i]);
        }
        em.close();
    }

    /*
     * Validates use of OrderColumn with ElementCollection of Embeddables
     */
    public void testElementCollectionEmbeddables() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        Game game = new Game();
       
        // Verify field name is the default via fm
        validateOrderColumnName(Game.class, "innings",
            "inningOrder");
       
        // Create a list of basic types
        Inning innings[] = new Inning[9];
        Collection<Inning> inningCol = new ArrayList<Inning>();
        Random rnd = new Random();
        for (int i = 8; i >= 0; i--) {
            innings[i] = new Inning(i, Math.abs(rnd.nextInt()) % 10,
                Math.abs(rnd.nextInt()) % 10);
        }
        // Add in reverse (correct) order
        for (int i = 8; i >= 0; i--) {
            inningCol.add(innings[i]);
        }
        game.setInnings(inningCol);
       
        em.getTransaction().begin();
        em.persist(game);
        em.getTransaction().commit();

        em.clear();
       
        Game newGame = em.find(Game.class, game.getId());
        assertNotNull(newGame);
        // Verify the order
        Inning[] inningArr = (Inning[])game.getInnings().
            toArray(new Inning[9]);
        for (int i = 0; i < 9; i++) {
            assertEquals(inningArr[i],
                innings[8-i]);
        }
        em.close();       
    }


    /*
     * Validates the use of the updatable on OrderColumn.  insertable=false
     * simply means the order column is omitted from the sql. Having the
     * appropriate field mapping will enforce that.
     */
    public void testOrderColumnInsertable() {
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        // Create a collection using secondary entities

        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "titles",
            "titles_ORDER");

        validateOrderColumnInsertable(emf, BattingOrder.class, "fixedBatters",
                false);
       
        em.close();
    }
   
    /*
     * Validates the use of the updatable on OrderColumn.  updatable=false
     * simply means the order column is omitted from the sql. Having the
     * appropriate field mapping will enforce that.
     */
    public void testOrderColumnUpdateable() {
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Verify field name is the default via fm
        validateOrderColumnName(BattingOrder.class, "titles",
            "titles_ORDER");

        validateOrderColumnUpdatable(emf, BattingOrder.class, "titles",
            false);
       
        em.close();
    }

    /*
     * Validates the use of the OrderColumn with o2o, o2m, m2m relationships
     * and collection table - with and without join tables.
     */
    public void testOrderColumnTable() {  
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        validateOrderColumnTable(emf, Owner.class, "cars",
            "OC_CAR", "car_o2m_order");
               
        validateOrderColumnTable(emf, Owner.class, "homes",
             "home_o2m_table", "homes_ORDER");

        validateOrderColumnTable(emf, Owner.class, "bikeColl",
             "bike_table", "bike_coll_order");

        validateOrderColumnTable(emf, Owner.class, "widgets",
                "widget_m2m_table", "widgets_ORDER");

        Owner owner = new Owner();
        Collection<Car> cars = new ArrayList<Car>();
        Collection<Home> homes = new ArrayList<Home>();
        Collection<Bicycle> bicycles = new ArrayList<Bicycle>();
        Collection<Widget> widgets = new ArrayList<Widget>();
        Collection<Owner> owners = new ArrayList<Owner>();
        owner.setCars(cars);
        owner.setHomes(homes);
        owner.setBikeColl(bicycles);
        owner.setWidgets(widgets);
       
        for (int i = 0;  i < 5; i++){
            Car car = new Car(2000 + 1, "Make"+i, "Model"+i);
            car.setOwner(owner);
            cars.add(car);
           
            Home home = new Home(2000 + i);
            homes.add(home);
           
            Bicycle bike = new Bicycle("Brand"+i, "Model"+i);
            bicycles.add(bike);  
           
            Widget widget = new Widget("Name"+i);
            widgets.add(widget);
            widget.setOwners(owners);
        }
       
        Object[] carArr = cars.toArray();
        Object[] homeArr = homes.toArray();
        Object[] bikeArr = bicycles.toArray();
        Object[] widgetArr = widgets.toArray();
       
        em.getTransaction().begin();
        em.persist(owner);
        em.getTransaction().commit();
        String oid = owner.getId();
       
        em.clear();
       
        // Run queries to ensure the query component uses the correct tables
        validateIndexAndValues(em, "Owner", "cars", 0,
                carArr, "id",
                oid);

        validateIndexAndValues(em, "Owner", "homes", 0,
                homeArr, "id",
                oid);

        validateIndexAndValues(em, "Owner", "widgets", 0,
                widgetArr, "id",
                oid);

        validateIndexAndValues(em, "Owner", "bikeColl", 0,
                bikeArr, "id",
                oid);
       
        em.close();
    }   

    /*
     * Validates the use of order column (via INDEX) in the predicate of a
     * JPQL query.
     */
    public void testOrderColumnPredicateQuery() {
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Query and verify the result
        String queryString = "SELECT w FROM Course c JOIN c.waitList w " +
            "WHERE c.name = :cname AND INDEX(w) = :widx";
        Query qry = em.createQuery(queryString);
        qry.setParameter("widx", 0);
        qry.setParameter("cname", "Course B");
        Student idx0 = (Student)qry.getSingleResult();
        assertNotNull(idx0);
        assertEquals(idx0, students[10]);

        qry.setParameter("widx", 1);
        idx0 = (Student)qry.getSingleResult();
        assertNotNull(idx0);
        assertEquals(idx0, students[11]);

        qry.setParameter("cname", "Course A");
        qry.setParameter("widx", 0);
        idx0 = (Student)qry.getSingleResult();
        assertNotNull(idx0);
        assertEquals(idx0, students[11]);

        qry.setParameter("widx", 1);
        idx0 = (Student)qry.getSingleResult();
        assertNotNull(idx0);
        assertEquals(idx0, students[10])
       
        em.close();
    }

    /*
     * Validates the use of order column (via INDEX) in the projection of
     * a JPQL query.
     */
    public void testOrderColumnProjectionQuery() {
       
        OpenJPAEntityManagerSPI em = emf.createEntityManager();

        // Query and verify the result
        String queryString = "SELECT INDEX(w) FROM Course c JOIN c.waitList w" +
            " WHERE c.name = :cname";
        Query qry = em.createQuery(queryString);
        qry.setParameter("cname", "Course A");
        List rlist = qry.getResultList();      
        assertNotNull(rlist);
        assertEquals(rlist.size(), 2);
        assertEquals(rlist.get(0), 0L);
        assertEquals(rlist.get(1), 1L);

        queryString = "SELECT INDEX(w) FROM Course c JOIN c.waitList w" +
            " WHERE c.name = :cname AND w.name = 'Student11'";
        qry = em.createQuery(queryString);
        qry.setParameter("cname", "Course B");
        Long idx = (Long)qry.getSingleResult();      
        assertNotNull(idx);
        assertEquals((Long)idx, (Long)1L);
       
        em.close();
    }
   
    /*
     * Create the data used by the query tests
     */
    private void createQueryData() {
        OpenJPAEntityManagerSPI em = emf.createEntityManager();
        // Add some data
        for (int i = 0; i < 12; i++) {
            students[i] = new Student("Student" + i);
        }
        Course courseA = new Course("Course A");
        Course courseB = new Course("Course B");
       
        HashSet<Course> courses = new HashSet<Course>();
        courses.add(courseA);
        courses.add(courseB);
        HashSet<Student> cAstudents = new HashSet<Student>();
        for (int i = 0; i < 5; i++) {
            cAstudents.add(students[i]);
            students[i].setCourses(courses);
        }
        courseA.setStudents(cAstudents);
        ArrayList<Student> cAwaitlist = new ArrayList<Student>();
        cAwaitlist.add(students[11]);
        cAwaitlist.add(students[10]);
        courseA.setWaitList(cAwaitlist);
       
        HashSet<Student> cBstudents = new HashSet<Student>();
        for (int i = 5; i < 10; i++) {
            cBstudents.add(students[i]);
        }
        courseB.setStudents(cBstudents);
        ArrayList<Student> cBwaitlist = new ArrayList<Student>();
        cBwaitlist.add(students[10]);
        cBwaitlist.add(students[11]);
        courseB.setWaitList(cBwaitlist);
       
        em.getTransaction().begin();
        em.persist(courseA);
        em.persist(courseB);
        em.getTransaction().commit();
        em.close();
    }
   
    private void validateIndexAndValues(OpenJPAEntityManagerSPI em,
            String entity, String indexedCol, int base, Object[] objs, String
            idField, Object idValue) {
        String queryString =
            "SELECT INDEX(b), b FROM " + entity + " a JOIN a." + indexedCol
                + " b WHERE a." + idField + " = :idVal";
        em.clear();
        Query qry = em.createQuery(queryString);
        qry.setParameter("idVal", idValue);
        List rlist = qry.getResultList()
       
        assertNotNull(rlist);
        assertEquals(objs.length, rlist.size());
        TreeMap<Long, Object> objMap = new TreeMap<Long, Object>();
        for (int i = 0; i < objs.length; i++)
        {
            Object[] rvals = (Object[])rlist.get(i);
            Long idx = (Long)rvals[0];
            Object objVal = rvals[1];
            objMap.put(idx, objVal);
        }
        for (int i = 0; i < objs.length; i++) {
            Object val = objMap.get((new Long(base + i)));
            assertEquals(val, objs[i]);
        }
    }

    private void validateCollIndexAndValues(OpenJPAEntityManagerSPI em,
        String entity, String indexedCol, int base, Object[] objs, String
        idField, Object idValue) {
    String queryString =
        "SELECT INDEX(b), b FROM " + entity + " a, IN(a." + indexedCol
            + ") b WHERE a." + idField + " = :idVal";
    em.clear();
    Query qry = em.createQuery(queryString);
    qry.setParameter("idVal", idValue);
    List rlist = qry.getResultList()
   
    assertNotNull(rlist);
    assertEquals(objs.length, rlist.size());
    TreeMap<Long, Object> objMap = new TreeMap<Long, Object>();
    for (int i = 0; i < objs.length; i++)
    {
        Object[] rvals = (Object[])rlist.get(i);
        Long idx = (Long)rvals[0];
        Object objVal = rvals[1];
        objMap.put(idx, objVal);
    }
    for (int i = 0; i < objs.length; i++) {
        Object val = objMap.get((new Long(base + i)));
        assertEquals(val, objs[i]);
    }
}

    private void validateOrderColumnName(Class clazz, String fieldName,
            String columnName) {
        validateOrderColumnName(emf, clazz, fieldName, columnName);
    }
   
    private Column getOrderColumn(OpenJPAEntityManagerFactorySPI emf1,
        Class clazz, String fieldName) {
        JDBCConfiguration conf = (JDBCConfiguration) emf1.getConfiguration();
        ClassMapping cls = conf.getMappingRepositoryInstance().
            getMapping(clazz, null, true);
        FieldMapping fm = cls.getFieldMapping(fieldName);
        Column oc = fm.getOrderColumn();
        assertNotNull(oc);
        return oc;
    }

    private void validateOrderColumnName(OpenJPAEntityManagerFactorySPI emf1,
        Class clazz, String fieldName, String columnName) {       
        Column oc = getOrderColumn(emf1, clazz, fieldName);
        assertTrue(oc.getName().equalsIgnoreCase(columnName));
    }

    private void validateOrderColumnTable(
            OpenJPAEntityManagerFactorySPI emf1,
            Class clazz, String fieldName, String tableName,
            String columnName) {       
            Column oc = getOrderColumn(emf1, clazz, fieldName);
            // Verify the oc has the correct table name
            assertTrue(oc.getTableName().equalsIgnoreCase(tableName));
            // Verify the table exists in the db
            assertTrue(tableAndColumnExists(emf1, null, tableName, null,
                columnName));
    }

    private void validateOrderColumnUpdatable(
            OpenJPAEntityManagerFactorySPI emf1, Class clazz, String fieldName,
            boolean updatable) {
            Column oc = getOrderColumn(emf1, clazz, fieldName);
            assertEquals(updatable, !oc.getFlag(Column.FLAG_DIRECT_UPDATE));
    }

    private void validateOrderColumnInsertable(
            OpenJPAEntityManagerFactorySPI emf1, Class clazz, String fieldName,
            boolean insertable) {
            Column oc = getOrderColumn(emf1, clazz, fieldName);
            assertEquals(insertable, !oc.getFlag(Column.FLAG_DIRECT_INSERT));
    }

    /**
     * Method to verify a table was created for the given name and schema
     */
    private boolean tableAndColumnExists(OpenJPAEntityManagerFactorySPI emf1,
            OpenJPAEntityManagerSPI em, String tableName, String schemaName,
            String columnName) {
        JDBCConfiguration conf = (JDBCConfiguration) emf1.getConfiguration();
        DBDictionary dict = conf.getDBDictionaryInstance();
        OpenJPAEntityManagerSPI em1 = em;
               
        // If no em supplied, create one
        if (em1 == null) {
            em1 = emf1.createEntityManager();
        }
        Connection conn = (Connection)em1.getConnection();
        try {
            DatabaseMetaData dbmd = conn.getMetaData();
            // (meta, catalog, schemaName, tableName, conn)
            Column[] cols = dict.getColumns(dbmd, null, null,
                    tableName, columnName, conn);
            if (cols != null && cols.length == 1) {
                Column col = cols[0];
                String colName = col.getName();
                if (col.getTableName().equalsIgnoreCase(tableName) &&
                    (schemaName == null ||
                    col.getSchemaName().equalsIgnoreCase(schemaName)) &&
                    colName.equalsIgnoreCase(columnName))
                    return true;
            }
        } catch (Throwable e) {
            fail("Unable to get column information.");
        } finally {
            if (em == null) {
                em1.close();
            }
        }
        return false;
    }
}
TOP

Related Classes of org.apache.openjpa.persistence.jdbc.order.TestOrderColumn

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.