Skip to content

Commit 428e0b7

Browse files
committed
HHH-11144 - orphanRemoval not working when other same-table-relations are initialized
Add test to prove that the issue does not replicate
1 parent 7c2a588 commit 428e0b7

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.jpa.test.orphan.onetomany;
8+
9+
import java.io.Serializable;
10+
import java.util.LinkedHashSet;
11+
import java.util.List;
12+
import java.util.Objects;
13+
import java.util.Set;
14+
import javax.persistence.CascadeType;
15+
import javax.persistence.Column;
16+
import javax.persistence.Entity;
17+
import javax.persistence.EntityManager;
18+
import javax.persistence.GeneratedValue;
19+
import javax.persistence.Id;
20+
import javax.persistence.Index;
21+
import javax.persistence.JoinColumn;
22+
import javax.persistence.ManyToOne;
23+
import javax.persistence.OneToMany;
24+
import javax.persistence.Table;
25+
26+
import org.hibernate.Hibernate;
27+
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
28+
29+
import org.hibernate.testing.FailureExpected;
30+
import org.hibernate.testing.TestForIssue;
31+
import org.hibernate.testing.transaction.TransactionUtil;
32+
import org.junit.Assert;
33+
import org.junit.Test;
34+
35+
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
36+
import static org.junit.Assert.assertEquals;
37+
38+
/**
39+
* @author Vlad Mihalcea
40+
*/
41+
public class DeleteOneToManyOrphansWithProxyInitializationTest extends BaseEntityManagerFunctionalTestCase {
42+
43+
private void createData() {
44+
doInJPA( this::entityManagerFactory, em -> {
45+
Item item1 = new Item();
46+
item1.setCode( "first" );
47+
em.persist( item1 );
48+
49+
Item item2 = new Item();
50+
item2.setCode( "second" );
51+
em.persist( item2 );
52+
53+
ItemRelation rel = new ItemRelation();
54+
rel.setParent( item1 );
55+
rel.setChild( item2 );
56+
item1.getLowerItemRelations().add( rel );
57+
item2.getHigherItemRelations().add( rel );
58+
em.persist( rel );
59+
} );
60+
}
61+
62+
@Test
63+
@TestForIssue(jiraKey = "HHH-11144")
64+
public void testOrphanedWhileManaged() {
65+
createData();
66+
67+
doInJPA( this::entityManagerFactory, em -> {
68+
Item item = em.createQuery("select x from Item x where x.code = 'first'", Item.class).getSingleResult();
69+
70+
Set<ItemRelation> lowerItemRelations = item.getLowerItemRelations();
71+
Hibernate.initialize( lowerItemRelations);
72+
73+
Set<ItemRelation> higherItemRelations = item.getHigherItemRelations();
74+
Hibernate.initialize(higherItemRelations);
75+
76+
Assert.assertEquals( 1, lowerItemRelations.size());
77+
78+
lowerItemRelations.clear();
79+
} );
80+
81+
doInJPA( this::entityManagerFactory, em -> {
82+
Item item = em.createQuery("select x from Item x where x.code = 'first'", Item.class).getSingleResult();
83+
84+
Set<ItemRelation> lowerItemRelations = item.getLowerItemRelations();
85+
Assert.assertEquals( 0, lowerItemRelations.size());
86+
} );
87+
}
88+
89+
@Override
90+
protected Class<?>[] getAnnotatedClasses() {
91+
return new Class[] {
92+
Item.class,
93+
ItemRelation.class
94+
};
95+
}
96+
97+
@Entity(name = "Item")
98+
@Table(name = "ITEM", indexes = @Index(columnList = "CODE", unique = true))
99+
public static class Item implements Serializable {
100+
private static final long serialVersionUID = 1L;
101+
102+
@Id
103+
@GeneratedValue
104+
protected Long id;
105+
106+
@Column
107+
protected String code;
108+
109+
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
110+
protected Set<ItemRelation> lowerItemRelations = new LinkedHashSet<>();
111+
112+
@OneToMany(mappedBy = "child", cascade = CascadeType.ALL, orphanRemoval = true)
113+
protected Set<ItemRelation> higherItemRelations = new LinkedHashSet<>();
114+
115+
@Override
116+
public int hashCode() {
117+
return Objects.hash( code );
118+
}
119+
120+
@Override
121+
public boolean equals(Object obj) {
122+
if ( this == obj ) {
123+
return true;
124+
}
125+
126+
if ( obj == null || !( obj instanceof Item ) ) {
127+
return false;
128+
}
129+
130+
Item other = (Item) obj;
131+
132+
return Objects.equals( code, other.getCode() );
133+
}
134+
135+
@Override
136+
public String toString() {
137+
return getClass().getSimpleName() + ": id=[" + id + "] code=[" + code + "]";
138+
}
139+
140+
public Long getId() {
141+
return id;
142+
}
143+
144+
public void setId(Long id) {
145+
this.id = id;
146+
}
147+
148+
public String getCode() {
149+
return code;
150+
}
151+
152+
public void setCode(String code) {
153+
this.code = code;
154+
}
155+
156+
public Set<ItemRelation> getLowerItemRelations() {
157+
return lowerItemRelations;
158+
}
159+
160+
public void setLowerItemRelations(Set<ItemRelation> lowerItemRelations) {
161+
this.lowerItemRelations = lowerItemRelations;
162+
}
163+
164+
public Set<ItemRelation> getHigherItemRelations() {
165+
return higherItemRelations;
166+
}
167+
168+
public void setHigherItemRelations(Set<ItemRelation> higherItemRelations) {
169+
this.higherItemRelations = higherItemRelations;
170+
}
171+
}
172+
173+
@Entity(name = "ItemRelation")
174+
@Table(name = "ITEM_RELATION",
175+
indexes = @Index(columnList = "PARENT_ID, CHILD_ID", unique = true))
176+
public static class ItemRelation implements Serializable {
177+
private static final long serialVersionUID = 1L;
178+
179+
@Id
180+
@GeneratedValue
181+
protected Long id;
182+
183+
@ManyToOne(optional = false)
184+
@JoinColumn(name = "PARENT_ID")
185+
private Item parent;
186+
187+
@ManyToOne(optional = false)
188+
@JoinColumn(name = "CHILD_ID")
189+
private Item child;
190+
191+
@Column(nullable = false, columnDefinition = "INT DEFAULT 0 NOT NULL")
192+
private int quantity = 1;
193+
194+
@Override
195+
public int hashCode() {
196+
return Objects.hash( parent, child );
197+
}
198+
199+
@Override
200+
public boolean equals(Object obj) {
201+
if ( this == obj ) {
202+
return true;
203+
}
204+
205+
if ( obj == null || !( obj instanceof ItemRelation ) ) {
206+
return false;
207+
}
208+
209+
ItemRelation other = (ItemRelation) obj;
210+
211+
return Objects.equals( parent, other.getParent() ) && Objects.equals( child, other.getChild() );
212+
}
213+
214+
@Override
215+
public String toString() {
216+
return getClass().getSimpleName() + ": id=[" + id + "] parent=[" + parent + "] child=[" + child + "]";
217+
}
218+
219+
public Item getParent() {
220+
return parent;
221+
}
222+
223+
public void setParent(Item parent) {
224+
this.parent = parent;
225+
}
226+
227+
public Item getChild() {
228+
return child;
229+
}
230+
231+
public void setChild(Item child) {
232+
this.child = child;
233+
}
234+
235+
public int getQuantity() {
236+
return quantity;
237+
}
238+
239+
public void setQuantity(int quantity) {
240+
this.quantity = quantity;
241+
}
242+
}
243+
}

0 commit comments

Comments
 (0)