Skip to content

Commit 976da8e

Browse files
dreab8sebersole
authored andcommitted
Revert "HHH-19179 Remove commit 816c976 by Alex Belyaev"
This reverts commit d9289c1.
1 parent bf3e949 commit 976da8e

File tree

2 files changed

+290
-0
lines changed

2 files changed

+290
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.cascade.circle;
6+
7+
import java.util.ArrayList;
8+
import java.util.Arrays;
9+
import java.util.HashSet;
10+
11+
import org.hibernate.cfg.Environment;
12+
13+
import org.hibernate.testing.orm.junit.DomainModel;
14+
import org.hibernate.testing.orm.junit.ServiceRegistry;
15+
import org.hibernate.testing.orm.junit.SessionFactory;
16+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
17+
import org.hibernate.testing.orm.junit.Setting;
18+
import org.junit.jupiter.api.AfterEach;
19+
import org.junit.jupiter.api.Test;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
23+
/**
24+
* The test case uses the following model:
25+
* <p>
26+
* <- ->
27+
* -- (N : 0,1) -- Tour
28+
* | <- ->
29+
* | -- (1 : N) -- (pickup) ----
30+
* <- -> | | |
31+
* Route -- (1 : N) -- Node Transport
32+
* | <- -> |
33+
* -- (1 : N) -- (delivery) --
34+
* <p>
35+
* Arrows indicate the direction of cascade-merge, cascade-persist, cascade-refresh
36+
* <p>
37+
* It reproduces the following issues:
38+
* https://hibernate.atlassian.net/browse/HHH-9512
39+
* <p>
40+
* This tests that cascades are done properly from each entity.
41+
*
42+
* @author Alex Belyaev (based on code by Pavol Zibrita and Gail Badner)
43+
*/
44+
@DomainModel(
45+
xmlMappings = {
46+
"org/hibernate/orm/test/cascade/circle/CascadeManagedAndTransient.hbm.xml"
47+
}
48+
)
49+
@SessionFactory
50+
@ServiceRegistry(
51+
settings = @Setting(name = Environment.CHECK_NULLABILITY, value = "true")
52+
)
53+
public class CascadeManagedAndTransientTest {
54+
55+
@AfterEach
56+
public void cleanupTest(SessionFactoryScope scope) {
57+
scope.inTransaction(
58+
session -> {
59+
session.createQuery( "delete from Transport" );
60+
session.createQuery( "delete from Tour" );
61+
session.createQuery( "delete from Node" );
62+
session.createQuery( "delete from Route" );
63+
session.createQuery( "delete from Vehicle" );
64+
}
65+
);
66+
}
67+
68+
@Test
69+
public void testAttachedChildInMerge(SessionFactoryScope scope) {
70+
fillInitialData( scope );
71+
72+
scope.inTransaction(
73+
session -> {
74+
Route route = (Route) session.createQuery( "FROM Route WHERE name = :name" )
75+
.setParameter( "name", "Route 1" )
76+
.uniqueResult();
77+
Node n2 = (Node) session.createQuery( "FROM Node WHERE name = :name" )
78+
.setParameter( "name", "Node 2" )
79+
.uniqueResult();
80+
Node n3 = (Node) session.createQuery( "FROM Node WHERE name = :name" )
81+
.setParameter( "name", "Node 3" )
82+
.uniqueResult();
83+
84+
Vehicle vehicle = new Vehicle();
85+
vehicle.setName( "Bus" );
86+
vehicle.setRoute( route );
87+
88+
Transport $2to3 = new Transport();
89+
$2to3.setName( "Transport 2 -> 3" );
90+
$2to3.setPickupNode( n2 );
91+
n2.getPickupTransports().add( $2to3 );
92+
$2to3.setDeliveryNode( n3 );
93+
n3.getDeliveryTransports().add( $2to3 );
94+
$2to3.setVehicle( vehicle );
95+
96+
vehicle.setTransports( new HashSet<Transport>( Arrays.asList( $2to3 ) ) );
97+
98+
// Try to save graph of transient entities (vehicle, transport) which contains attached entities (node2, node3)
99+
Vehicle managedVehicle = (Vehicle) session.merge( vehicle );
100+
checkNewVehicle( managedVehicle );
101+
102+
session.flush();
103+
session.clear();
104+
105+
assertEquals( 3, session.createQuery( "FROM Transport" ).list().size() );
106+
assertEquals( 2, session.createQuery( "FROM Vehicle" ).list().size() );
107+
assertEquals( 4, session.createQuery( "FROM Node" ).list().size() );
108+
109+
Vehicle newVehicle = (Vehicle) session.createQuery( "FROM Vehicle WHERE name = :name" )
110+
.setParameter( "name", "Bus" )
111+
.uniqueResult();
112+
checkNewVehicle( newVehicle );
113+
}
114+
);
115+
}
116+
117+
private void checkNewVehicle(Vehicle newVehicle) {
118+
assertEquals( "Bus", newVehicle.getName() );
119+
assertEquals( 1, newVehicle.getTransports().size() );
120+
Transport t = (Transport) newVehicle.getTransports().iterator().next();
121+
assertEquals( "Transport 2 -> 3", t.getName() );
122+
assertEquals( "Node 2", t.getPickupNode().getName() );
123+
assertEquals( "Node 3", t.getDeliveryNode().getName() );
124+
}
125+
126+
private void fillInitialData(SessionFactoryScope scope) {
127+
Tour tour = new Tour();
128+
tour.setName( "Tour 1" );
129+
130+
Route route = new Route();
131+
route.setName( "Route 1" );
132+
133+
ArrayList<Node> nodes = new ArrayList<Node>();
134+
for ( int i = 0; i < 4; i++ ) {
135+
Node n = new Node();
136+
n.setName( "Node " + i );
137+
n.setTour( tour );
138+
n.setRoute( route );
139+
nodes.add( n );
140+
}
141+
142+
tour.setNodes( new HashSet<>( nodes ) );
143+
route.setNodes( new HashSet<>( Arrays.asList( nodes.get( 0 ), nodes.get( 1 ), nodes.get( 2 ) ) ) );
144+
145+
Vehicle vehicle = new Vehicle();
146+
vehicle.setName( "Car" );
147+
route.setVehicles( new HashSet<>( Arrays.asList( vehicle ) ) );
148+
vehicle.setRoute( route );
149+
150+
Transport $0to1 = new Transport();
151+
$0to1.setName( "Transport 0 -> 1" );
152+
$0to1.setPickupNode( nodes.get( 0 ) );
153+
$0to1.setDeliveryNode( nodes.get( 1 ) );
154+
$0to1.setVehicle( vehicle );
155+
156+
Transport $1to2 = new Transport();
157+
$1to2.setName( "Transport 1 -> 2" );
158+
$1to2.setPickupNode( nodes.get( 1 ) );
159+
$1to2.setDeliveryNode( nodes.get( 2 ) );
160+
$1to2.setVehicle( vehicle );
161+
162+
vehicle.setTransports( new HashSet<>( Arrays.asList( $0to1, $1to2 ) ) );
163+
164+
scope.inTransaction(
165+
session ->
166+
session.persist( tour )
167+
);
168+
}
169+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
~ Hibernate, Relational Persistence for Idiomatic Java
4+
~
5+
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
6+
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
7+
-->
8+
<!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
9+
10+
<hibernate-mapping package="org.hibernate.orm.test.cascade.circle">
11+
12+
<class name="Route" table="HB_Route">
13+
14+
<id name="routeID" type="long"><generator class="native"/></id>
15+
<version name="version" column="VERS" type="long" />
16+
17+
<property name="name" type="string" not-null="true"/>
18+
19+
<set name="nodes" inverse="true" cascade="persist,merge,refresh">
20+
<key column="routeID"/>
21+
<one-to-many class="Node"/>
22+
</set>
23+
<set name="vehicles" inverse="true" cascade="persist,merge,refresh">
24+
<key column="routeID"/>
25+
<one-to-many class="Vehicle"/>
26+
</set>
27+
</class>
28+
29+
<class name="Tour" table="HB_Tour">
30+
31+
<id name="tourID" type="long"><generator class="native"/></id>
32+
<version name="version" column="VERS" type="long" />
33+
34+
<property name="name" type="string" not-null="true"/>
35+
36+
<set name="nodes" inverse="true" lazy="true" cascade="merge,refresh,persist">
37+
<key column="tourID"/>
38+
<one-to-many class="Node"/>
39+
</set>
40+
</class>
41+
42+
<class name="Transport" table="HB_Transport">
43+
44+
<id name="transportID" type="long"><generator class="native"/></id>
45+
<version name="version" column="VERS" type="long" />
46+
47+
<property name="name" type="string" not-null="true"/>
48+
49+
<many-to-one name="pickupNode"
50+
column="pickupNodeID"
51+
unique="true"
52+
not-null="true"
53+
cascade="merge,refresh,persist"
54+
lazy="false"/>
55+
56+
<many-to-one name="deliveryNode"
57+
column="deliveryNodeID"
58+
unique="true"
59+
not-null="true"
60+
cascade="merge,refresh,persist"
61+
lazy="false"/>
62+
63+
<many-to-one name="vehicle"
64+
column="vehicleID"
65+
unique="false"
66+
not-null="true"
67+
cascade="merge,refresh,persist"
68+
lazy="false"/>
69+
</class>
70+
71+
<class name="Vehicle" table="HB_Vehicle">
72+
<id name="vehicleID" type="long"><generator class="native"/></id>
73+
<version name="version" column="VERS" type="long" />
74+
75+
<property name="name"/>
76+
<set name="transports" inverse="false" lazy="true" cascade="merge,refresh,persist">
77+
<key column="vehicleID"/>
78+
<one-to-many class="Transport" not-found="exception"/>
79+
</set>
80+
<many-to-one name="route"
81+
column="routeID"
82+
unique="false"
83+
not-null="false"
84+
cascade="merge,refresh,persist"
85+
lazy="false"/>
86+
</class>
87+
88+
89+
<class name="Node" table="HB_Node">
90+
91+
<id name="nodeID" type="long"><generator class="native"/></id>
92+
<version name="version" column="VERS" type="long" />
93+
94+
<property name="name" type="string" not-null="true"/>
95+
96+
<set name="deliveryTransports" inverse="true" lazy="true" cascade="merge,refresh,persist">
97+
<key column="deliveryNodeID"/>
98+
<one-to-many class="Transport"/>
99+
</set>
100+
101+
<set name="pickupTransports" inverse="true" lazy="true" cascade="merge,refresh,persist">
102+
<key column="pickupNodeID"/>
103+
<one-to-many class="Transport"/>
104+
</set>
105+
106+
<many-to-one name="route"
107+
column="routeID"
108+
unique="false"
109+
not-null="true"
110+
cascade="merge,refresh,persist"
111+
lazy="false"/>
112+
113+
<many-to-one name="tour"
114+
column="tourID"
115+
unique="false"
116+
not-null="true"
117+
cascade="merge,refresh,persist"
118+
lazy="false"/>
119+
</class>
120+
121+
</hibernate-mapping>

0 commit comments

Comments
 (0)