/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.cascade.circle;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* The test case uses the following model:
*
* <- ->
* -- (N : 0,1) -- Tour
* | <- ->
* | -- (1 : N) -- (pickup) ----
* -> | | |
* Route -- (1 : N) - Node Transport
* | | <- -> | |
* | -- (1 : N) -- (delivery) -- |
* | |
* | -> -> |
* -------- (1 : N) ---- Vehicle--(1 : N)------------
*
* Arrows indicate the direction of cascade-merge.
* <p/>
* I believe it reproduces the following issue:
* http://opensource.atlassian.com/projects/hibernate/browse/HHH-3544
*
* @author Gail Badner (based on original model provided by Pavol Zibrita)
*/
public class CascadeMergeToChildBeforeParentTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] {
"cascade/circle/CascadeMergeToChildBeforeParent.hbm.xml"
};
}
@Override
public void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.CHECK_NULLABILITY, "true" );
}
@Override
protected void cleanupTest() {
Session s = openSession();
s.beginTransaction();
s.createQuery( "delete from Transport" );
s.createQuery( "delete from Tour" );
s.createQuery( "delete from Node" );
s.createQuery( "delete from Route" );
s.createQuery( "delete from Vehicle" );
}
@Test
public void testMerge() {
Session s = openSession();
s.beginTransaction();
Route route = new Route();
route.setName( "routeA" );
s.save( route );
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
route = (Route) s.get( Route.class, new Long( 1 ) );
route.setTransientField( new String( "sfnaouisrbn" ) );
Tour tour = new Tour();
tour.setName( "tourB" );
Node pickupNode = new Node();
pickupNode.setName( "pickupNodeB" );
Node deliveryNode = new Node();
deliveryNode.setName( "deliveryNodeB" );
pickupNode.setRoute( route );
pickupNode.setTour( tour );
pickupNode.setTransientField( "pickup node aaaaaaaaaaa" );
deliveryNode.setRoute( route );
deliveryNode.setTour( tour );
deliveryNode.setTransientField( "delivery node aaaaaaaaa" );
tour.getNodes().add( pickupNode );
tour.getNodes().add( deliveryNode );
route.getNodes().add( pickupNode );
route.getNodes().add( deliveryNode );
Route mergedRoute = (Route) s.merge( route );
s.getTransaction().commit();
s.close();
}
@Test
public void testMergeTransientChildBeforeTransientParent() {
// This test fails because the merge algorithm tries to save a
// transient child (transport) before cascade-merge gets its
// transient parent (vehicle); merge does not cascade from the
// child to the parent.
Session s = openSession();
s.beginTransaction();
Route route = new Route();
route.setName( "routeA" );
s.save( route );
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
route = (Route) s.get( Route.class, new Long( 1 ) );
route.setTransientField( new String( "sfnaouisrbn" ) );
Tour tour = new Tour();
tour.setName( "tourB" );
Transport transport = new Transport();
transport.setName( "transportB" );
Node pickupNode = new Node();
pickupNode.setName( "pickupNodeB" );
Node deliveryNode = new Node();
deliveryNode.setName( "deliveryNodeB" );
Vehicle vehicle = new Vehicle();
vehicle.setName( "vehicleB" );
pickupNode.setRoute( route );
pickupNode.setTour( tour );
pickupNode.getPickupTransports().add( transport );
pickupNode.setTransientField( "pickup node aaaaaaaaaaa" );
deliveryNode.setRoute( route );
deliveryNode.setTour( tour );
deliveryNode.getDeliveryTransports().add( transport );
deliveryNode.setTransientField( "delivery node aaaaaaaaa" );
tour.getNodes().add( pickupNode );
tour.getNodes().add( deliveryNode );
route.getNodes().add( pickupNode );
route.getNodes().add( deliveryNode );
route.getVehicles().add( vehicle );
transport.setPickupNode( pickupNode );
transport.setDeliveryNode( deliveryNode );
transport.setVehicle( vehicle );
transport.setTransientField( "aaaaaaaaaaaaaa" );
vehicle.getTransports().add( transport );
vehicle.setTransientField( "anewvalue" );
vehicle.setRoute( route );
Route mergedRoute = (Route) s.merge( route );
s.getTransaction().commit();
s.close();
}
@Test
public void testMergeData3Nodes() {
Session s = openSession();
s.beginTransaction();
Route route = new Route();
route.setName( "routeA" );
s.save( route );
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
route = (Route) s.get( Route.class, new Long( 1 ) );
route.setTransientField( new String( "sfnaouisrbn" ) );
Tour tour = new Tour();
tour.setName( "tourB" );
Transport transport1 = new Transport();
transport1.setName( "TRANSPORT1" );
Transport transport2 = new Transport();
transport2.setName( "TRANSPORT2" );
Node node1 = new Node();
node1.setName( "NODE1" );
Node node2 = new Node();
node2.setName( "NODE2" );
Node node3 = new Node();
node3.setName( "NODE3" );
Vehicle vehicle = new Vehicle();
vehicle.setName( "vehicleB" );
node1.setRoute( route );
node1.setTour( tour );
node1.getPickupTransports().add( transport1 );
node1.setTransientField( "node 1" );
node2.setRoute( route );
node2.setTour( tour );
node2.getDeliveryTransports().add( transport1 );
node2.getPickupTransports().add( transport2 );
node2.setTransientField( "node 2" );
node3.setRoute( route );
node3.setTour( tour );
node3.getDeliveryTransports().add( transport2 );
node3.setTransientField( "node 3" );
tour.getNodes().add( node1 );
tour.getNodes().add( node2 );
tour.getNodes().add( node3 );
route.getNodes().add( node1 );
route.getNodes().add( node2 );
route.getNodes().add( node3 );
route.getVehicles().add( vehicle );
transport1.setPickupNode( node1 );
transport1.setDeliveryNode( node2 );
transport1.setVehicle( vehicle );
transport1.setTransientField( "aaaaaaaaaaaaaa" );
transport2.setPickupNode( node2 );
transport2.setDeliveryNode( node3 );
transport2.setVehicle( vehicle );
transport2.setTransientField( "bbbbbbbbbbbbb" );
vehicle.getTransports().add( transport1 );
vehicle.getTransports().add( transport2 );
vehicle.setTransientField( "anewvalue" );
vehicle.setRoute( route );
Route mergedRoute = (Route) s.merge( route );
s.getTransaction().commit();
s.close();
}
}