Skip to content

Commit d7400b5

Browse files
committed
HHH-14103 : Add test cases showing that an entity's transient attribute can be overridden to be persistent in entity subclasses
(cherry picked from commit fb40f8e)
1 parent 7317331 commit d7400b5

File tree

4 files changed

+1514
-0
lines changed

4 files changed

+1514
-0
lines changed
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
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.test.inheritance;
8+
9+
import java.util.List;
10+
import javax.persistence.Column;
11+
import javax.persistence.ConstraintMode;
12+
import javax.persistence.DiscriminatorColumn;
13+
import javax.persistence.Entity;
14+
import javax.persistence.ForeignKey;
15+
import javax.persistence.Id;
16+
import javax.persistence.Inheritance;
17+
import javax.persistence.InheritanceType;
18+
import javax.persistence.JoinColumn;
19+
import javax.persistence.ManyToOne;
20+
import javax.persistence.OneToOne;
21+
import javax.persistence.Table;
22+
import javax.persistence.Transient;
23+
import javax.persistence.criteria.CriteriaBuilder;
24+
import javax.persistence.criteria.CriteriaQuery;
25+
import javax.persistence.criteria.ParameterExpression;
26+
import javax.persistence.criteria.Predicate;
27+
import javax.persistence.criteria.Root;
28+
29+
import org.hibernate.testing.FailureExpected;
30+
import org.hibernate.testing.TestForIssue;
31+
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
32+
import org.junit.After;
33+
import org.junit.Before;
34+
import org.junit.Test;
35+
36+
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
37+
import static org.junit.Assert.assertEquals;
38+
import static org.junit.Assert.assertNotNull;
39+
import static org.junit.Assert.assertSame;
40+
import static org.junit.Assert.assertTrue;
41+
42+
@TestForIssue(jiraKey = "HHH-14103")
43+
public class TransientOverrideAsPersistentJoined extends BaseNonConfigCoreFunctionalTestCase {
44+
45+
@Test
46+
public void testFindByRootClass() {
47+
doInHibernate( this::sessionFactory, session -> {
48+
final Employee editor = session.find( Employee.class, "Jane Smith" );
49+
assertNotNull( editor );
50+
assertEquals( "Senior Editor", editor.getTitle() );
51+
final Employee writer = session.find( Employee.class, "John Smith" );
52+
assertTrue( Writer.class.isInstance( writer ) );
53+
assertEquals( "Writing", writer.getTitle() );
54+
assertNotNull( ( (Writer) writer ).getGroup() );
55+
final Group group = ( (Writer) writer ).getGroup();
56+
assertEquals( writer.getTitle(), group.getName() );
57+
final Job jobEditor = session.find( Job.class, "Edit" );
58+
assertSame( editor, jobEditor.getEmployee() );
59+
final Job jobWriter = session.find( Job.class, "Write" );
60+
assertSame( writer, jobWriter.getEmployee() );
61+
});
62+
}
63+
64+
@Test
65+
public void testFindBySubclass() {
66+
doInHibernate( this::sessionFactory, session -> {
67+
final Editor editor = session.find( Editor.class, "Jane Smith" );
68+
assertNotNull( editor );
69+
assertEquals( "Senior Editor", editor.getTitle() );
70+
final Writer writer = session.find( Writer.class, "John Smith" );
71+
assertEquals( "Writing", writer.getTitle() );
72+
assertNotNull( writer.getGroup() );
73+
final Group group = writer.getGroup();
74+
assertEquals( writer.getTitle(), group.getName() );
75+
final Job jobEditor = session.find( Job.class, "Edit" );
76+
assertSame( editor, jobEditor.getEmployee() );
77+
final Job jobWriter = session.find( Job.class, "Write" );
78+
assertSame( writer, jobWriter.getEmployee() );
79+
});
80+
}
81+
82+
@Test
83+
public void testQueryByRootClass() {
84+
doInHibernate( this::sessionFactory, session -> {
85+
final List<Employee> employees = session.createQuery( "from Employee", Employee.class )
86+
.getResultList();
87+
assertEquals( 2, employees.size() );
88+
assertTrue( Editor.class.isInstance( employees.get( 0 ) ) );
89+
assertTrue( Writer.class.isInstance( employees.get( 1 ) ) );
90+
final Editor editor = (Editor) employees.get( 0 );
91+
assertEquals( "Senior Editor", editor.getTitle() );
92+
final Writer writer = (Writer) employees.get( 1 );
93+
assertEquals( "Writing", writer.getTitle() );
94+
assertNotNull( writer.getGroup() );
95+
final Group group = writer.getGroup();
96+
assertEquals( writer.getTitle(), group.getName() );
97+
});
98+
}
99+
100+
@Test
101+
@FailureExpected( jiraKey = "HHH-12981")
102+
public void testQueryByRootClassAndOverridenProperty() {
103+
doInHibernate( this::sessionFactory, session -> {
104+
final Employee editor = session.createQuery( "from Employee where title=:title", Employee.class )
105+
.setParameter( "title", "Senior Editor" )
106+
.getSingleResult();
107+
assertTrue( Editor.class.isInstance( editor ) );
108+
109+
final Employee writer = session.createQuery( "from Employee where title=:title", Employee.class )
110+
.setParameter( "title", "Writing" )
111+
.getSingleResult();
112+
assertTrue( Writer.class.isInstance( writer ) );
113+
assertNotNull( ( (Writer) writer ).getGroup() );
114+
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
115+
});
116+
}
117+
118+
@Test
119+
@FailureExpected( jiraKey = "HHH-12981")
120+
public void testQueryByRootClassAndOverridenPropertyTreat() {
121+
doInHibernate( this::sessionFactory, session -> {
122+
final Employee editor = session.createQuery( "from Employee e where treat( e as Editor ).title=:title", Employee.class )
123+
.setParameter( "title", "Senior Editor" )
124+
.getSingleResult();
125+
assertTrue( Editor.class.isInstance( editor ) );
126+
127+
final Employee writer = session.createQuery( "from Employee e where treat( e as Writer).title=:title", Employee.class )
128+
.setParameter( "title", "Writing" )
129+
.getSingleResult();
130+
assertTrue( Writer.class.isInstance( writer ) );
131+
assertNotNull( ( (Writer) writer ).getGroup() );
132+
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
133+
});
134+
}
135+
136+
@Test
137+
public void testQueryBySublassAndOverridenProperty() {
138+
doInHibernate( this::sessionFactory, session -> {
139+
final Editor editor = session.createQuery( "from Editor where title=:title", Editor.class )
140+
.setParameter( "title", "Senior Editor" )
141+
.getSingleResult();
142+
assertTrue( Editor.class.isInstance( editor ) );
143+
144+
final Writer writer = session.createQuery( "from Writer where title=:title", Writer.class )
145+
.setParameter( "title", "Writing" )
146+
.getSingleResult();
147+
assertNotNull( writer.getGroup() );
148+
assertEquals( writer.getTitle(), writer.getGroup().getName() );
149+
});
150+
}
151+
152+
@Test
153+
@FailureExpected( jiraKey = "HHH-12981")
154+
public void testCriteriaQueryByRootClassAndOverridenProperty() {
155+
doInHibernate( this::sessionFactory, session -> {
156+
157+
final CriteriaBuilder builder = session.getCriteriaBuilder();
158+
159+
final CriteriaQuery<Employee> query = builder.createQuery( Employee.class );
160+
final Root<Employee> root = query.from( Employee.class );
161+
final ParameterExpression<String> parameter = builder.parameter( String.class, "title" );
162+
163+
final Predicate predicateEditor = builder.equal(
164+
builder.treat( root, Editor.class ).get( "title" ),
165+
parameter
166+
);
167+
query.where( predicateEditor );
168+
final Employee editor = session.createQuery( query )
169+
.setParameter( "title", "Senior Editor" )
170+
.getSingleResult();
171+
assertTrue( Editor.class.isInstance( editor ) );
172+
173+
final Predicate predicateWriter = builder.equal(
174+
builder.treat( root, Writer.class ).get( "title" ),
175+
parameter
176+
);
177+
query.where( predicateWriter );
178+
final Employee writer = session.createQuery( query )
179+
.setParameter( "title", "Writing" )
180+
.getSingleResult();
181+
assertTrue( Writer.class.isInstance( writer ) );
182+
assertNotNull( ( (Writer) writer ).getGroup() );
183+
assertEquals( writer.getTitle(), ( (Writer) writer ).getGroup() .getName() );
184+
});
185+
}
186+
187+
@Before
188+
public void setupData() {
189+
190+
doInHibernate( this::sessionFactory, session -> {
191+
Job jobEditor = new Job("Edit");
192+
jobEditor.setEmployee(new Editor("Jane Smith", "Senior Editor"));
193+
Job jobWriter= new Job("Write");
194+
jobWriter.setEmployee(new Writer("John Smith", new Group("Writing")));
195+
196+
Employee editor = jobEditor.getEmployee();
197+
Employee writer = jobWriter.getEmployee();
198+
Group group = Writer.class.cast( writer ).getGroup();
199+
200+
session.persist( editor );
201+
session.persist( group );
202+
session.persist( writer );
203+
session.persist( jobEditor );
204+
session.persist( jobWriter );
205+
});
206+
}
207+
208+
@After
209+
public void cleanupData() {
210+
doInHibernate( this::sessionFactory, session -> {
211+
session.createQuery( "delete from Job" ).executeUpdate();
212+
session.createQuery( "delete from Employee" ).executeUpdate();
213+
session.createQuery( "delete from Group" ).executeUpdate();
214+
});
215+
}
216+
217+
@Override
218+
protected Class<?>[] getAnnotatedClasses() {
219+
return new Class<?>[] {
220+
Employee.class,
221+
Editor.class,
222+
Writer.class,
223+
Group.class,
224+
Job.class
225+
};
226+
}
227+
228+
@Entity(name="Employee")
229+
@Inheritance(strategy = InheritanceType.JOINED)
230+
@DiscriminatorColumn(name="department")
231+
public static abstract class Employee {
232+
private String name;
233+
private String title;
234+
235+
protected Employee(String name) {
236+
this();
237+
setName(name);
238+
}
239+
240+
@Id
241+
public String getName() {
242+
return name;
243+
}
244+
245+
@Transient
246+
public String getTitle() {
247+
return title;
248+
}
249+
250+
protected Employee() {
251+
// this form used by Hibernate
252+
}
253+
254+
protected void setName(String name) {
255+
this.name = name;
256+
}
257+
258+
protected void setTitle(String title) {
259+
this.title = title;
260+
}
261+
}
262+
263+
@Entity(name = "Editor")
264+
public static class Editor extends Employee {
265+
public Editor(String name, String title) {
266+
super(name);
267+
setTitle( title );
268+
}
269+
270+
@Column(name = "e_title")
271+
public String getTitle() {
272+
return super.getTitle();
273+
}
274+
275+
public void setTitle(String title) {
276+
super.setTitle( title );
277+
}
278+
279+
protected Editor() {
280+
// this form used by Hibernate
281+
super();
282+
}
283+
}
284+
285+
@Entity(name = "Writer")
286+
public static class Writer extends Employee {
287+
private Group group;
288+
289+
public Writer(String name, Group group) {
290+
super(name);
291+
setGroup(group);
292+
}
293+
294+
// Cannot have a constraint on e_title because
295+
// Editor#title (which uses the same e_title column) can be non-null,
296+
// and there is no associated group.
297+
@ManyToOne(optional = false)
298+
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
299+
public Group getGroup() {
300+
return group;
301+
}
302+
303+
@Column(name = "e_title", insertable = false, updatable = false)
304+
public String getTitle() {
305+
return super.getTitle();
306+
}
307+
308+
public void setTitle(String title) {
309+
super.setTitle( title );
310+
}
311+
312+
protected Writer() {
313+
// this form used by Hibernate
314+
super();
315+
}
316+
317+
protected void setGroup(Group group) {
318+
this.group = group;
319+
setTitle( group.getName() );
320+
}
321+
}
322+
323+
@Entity(name = "Group")
324+
@Table(name = "WorkGroup")
325+
public static class Group {
326+
private String name;
327+
328+
public Group(String name) {
329+
this();
330+
setName(name);
331+
}
332+
333+
@Id
334+
public String getName() {
335+
return name;
336+
}
337+
338+
protected Group() {
339+
// this form used by Hibernate
340+
}
341+
342+
protected void setName(String name) {
343+
this.name = name;
344+
}
345+
}
346+
347+
@Entity(name = "Job")
348+
public static class Job {
349+
private String name;
350+
private Employee employee;
351+
352+
public Job(String name) {
353+
this();
354+
setName(name);
355+
}
356+
357+
@Id
358+
public String getName() {
359+
return name;
360+
}
361+
362+
@OneToOne
363+
@JoinColumn(name="employee_name")
364+
public Employee getEmployee() {
365+
return employee;
366+
}
367+
368+
protected Job() {
369+
// this form used by Hibernate
370+
}
371+
372+
protected void setName(String name) {
373+
this.name = name;
374+
}
375+
376+
protected void setEmployee(Employee e) {
377+
this.employee = e;
378+
}
379+
}
380+
}

0 commit comments

Comments
 (0)