Skip to content

Commit 819f92c

Browse files
committed
HHH-13269 - Embeddable collection regression due to HHH-11544
1 parent b843b3e commit 819f92c

File tree

3 files changed

+325
-3
lines changed

3 files changed

+325
-3
lines changed

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import org.hibernate.internal.CoreMessageLogger;
1717
import org.hibernate.internal.log.DeprecationLogger;
1818
import org.hibernate.internal.util.StringHelper;
19+
import org.hibernate.loader.plan.spi.EntityQuerySpace;
20+
import org.hibernate.loader.plan.spi.QuerySpace;
1921
import org.hibernate.persister.collection.QueryableCollection;
2022
import org.hibernate.persister.entity.AbstractEntityPersister;
2123
import org.hibernate.persister.entity.EntityPersister;
@@ -498,7 +500,7 @@ private void dereferenceEntityJoin(String classAlias, EntityType propertyType, b
498500

499501
JoinSequence joinSequence;
500502

501-
if ( joinColumns.length == 0 ) {
503+
if ( joinColumns.length == 0 && lhsFromElement instanceof EntityQuerySpace ) {
502504
// When no columns are available, this is a special join that involves multiple subtypes
503505
String lhsTableAlias = getLhs().getFromElement().getTableAlias();
504506

hibernate-core/src/main/java/org/hibernate/loader/plan/exec/internal/LoadQueryJoinAndFetchProcessor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ else if ( !StringHelper.isEmpty( joinConditions ) ) {
259259
);
260260

261261
String[] joinColumns = join.resolveAliasedLeftHandSideJoinConditionColumns( lhsTableAlias );
262-
if ( joinColumns.length == 0 ) {
262+
QuerySpace lhsQuerySpace = join.getLeftHandSide();
263+
if ( joinColumns.length == 0 && lhsQuerySpace instanceof EntityQuerySpace ) {
263264
// When no columns are available, this is a special join that involves multiple subtypes
264-
AbstractEntityPersister persister = (AbstractEntityPersister) ( (EntityQuerySpace) join.getLeftHandSide() ).getEntityPersister();
265+
EntityQuerySpace entityQuerySpace = (EntityQuerySpace) lhsQuerySpace;
266+
AbstractEntityPersister persister = (AbstractEntityPersister) entityQuerySpace.getEntityPersister();
265267

266268
String[][] polyJoinColumns = persister.getPolymorphicJoinColumns(
267269
lhsTableAlias,
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
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.mapping;
8+
9+
import java.io.Serializable;
10+
import java.util.Collections;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Locale;
14+
import java.util.Map;
15+
import java.util.Set;
16+
import javax.persistence.AssociationOverride;
17+
import javax.persistence.Basic;
18+
import javax.persistence.Column;
19+
import javax.persistence.ElementCollection;
20+
import javax.persistence.Embeddable;
21+
import javax.persistence.Embedded;
22+
import javax.persistence.Entity;
23+
import javax.persistence.EntityManager;
24+
import javax.persistence.FetchType;
25+
import javax.persistence.GeneratedValue;
26+
import javax.persistence.GenerationType;
27+
import javax.persistence.Id;
28+
import javax.persistence.Inheritance;
29+
import javax.persistence.InheritanceType;
30+
import javax.persistence.JoinColumn;
31+
import javax.persistence.JoinTable;
32+
import javax.persistence.Lob;
33+
import javax.persistence.ManyToOne;
34+
import javax.persistence.MapKeyColumn;
35+
import javax.persistence.OneToMany;
36+
import javax.persistence.OrderBy;
37+
import javax.persistence.Table;
38+
import javax.persistence.TypedQuery;
39+
import javax.persistence.criteria.CriteriaBuilder;
40+
import javax.persistence.criteria.CriteriaQuery;
41+
import javax.persistence.criteria.Root;
42+
43+
import org.hibernate.Hibernate;
44+
import org.hibernate.annotations.Type;
45+
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
46+
import org.hibernate.jpa.test.criteria.components.Alias;
47+
import org.hibernate.jpa.test.criteria.components.Client;
48+
import org.hibernate.jpa.test.criteria.components.Client_;
49+
import org.hibernate.jpa.test.criteria.components.Name_;
50+
51+
import org.hibernate.testing.TestForIssue;
52+
import org.junit.Assert;
53+
import org.junit.Test;
54+
55+
import static org.junit.Assert.assertTrue;
56+
57+
/**
58+
* @author Vlad Mihalcea
59+
*/
60+
public class NestedEmbeddableTest extends BaseEntityManagerFunctionalTestCase {
61+
62+
@Override
63+
public Class[] getAnnotatedClasses() {
64+
return new Class[] {
65+
Categorization.class,
66+
Category.class,
67+
CcmObject.class,
68+
Domain.class
69+
};
70+
}
71+
72+
@Test
73+
public void test() {
74+
75+
}
76+
77+
@Entity
78+
@Table(name = "CATEGORIZATIONS")
79+
public static class Categorization implements Serializable {
80+
81+
@Id
82+
@Column(name = "CATEGORIZATION_ID")
83+
@GeneratedValue(strategy = GenerationType.AUTO)
84+
private long categorizationId;
85+
86+
@ManyToOne
87+
@JoinColumn(name = "CATEGORY_ID")
88+
private Category category;
89+
90+
@ManyToOne
91+
@JoinColumn(name = "OBJECT_ID")
92+
private CcmObject categorizedObject;
93+
94+
public long getCategorizationId() {
95+
return categorizationId;
96+
}
97+
98+
public void setCategorizationId(long categorizationId) {
99+
this.categorizationId = categorizationId;
100+
}
101+
102+
public Category getCategory() {
103+
return category;
104+
}
105+
106+
public void setCategory(Category category) {
107+
this.category = category;
108+
}
109+
110+
public CcmObject getCategorizedObject() {
111+
return categorizedObject;
112+
}
113+
114+
public void setCategorizedObject(CcmObject categorizedObject) {
115+
this.categorizedObject = categorizedObject;
116+
}
117+
}
118+
119+
@Entity
120+
@Table(name = "CATEGORIES")
121+
public static class Category extends CcmObject implements Serializable {
122+
123+
private static final long serialVersionUID = 1L;
124+
125+
@Column(name = "NAME", nullable = false)
126+
private String name;
127+
128+
@Embedded
129+
@AssociationOverride(
130+
name = "values",
131+
joinTable = @JoinTable(name = "CATEGORY_TITLES",
132+
joinColumns = {
133+
@JoinColumn(name = "OBJECT_ID")}
134+
))
135+
private LocalizedString title;
136+
137+
@Embedded
138+
@AssociationOverride(
139+
name = "values",
140+
joinTable = @JoinTable(name = "CATEGORY_DESCRIPTIONS",
141+
joinColumns = {
142+
@JoinColumn(name = "OBJECT_ID")}
143+
))
144+
private LocalizedString description;
145+
146+
@OneToMany(mappedBy = "category", fetch = FetchType.LAZY)
147+
@OrderBy("objectOrder ASC")
148+
private List<Categorization> objects;
149+
150+
public String getName() {
151+
return name;
152+
}
153+
154+
public void setName(String name) {
155+
this.name = name;
156+
}
157+
158+
public LocalizedString getTitle() {
159+
return title;
160+
}
161+
162+
public void setTitle(LocalizedString title) {
163+
this.title = title;
164+
}
165+
166+
public LocalizedString getDescription() {
167+
return description;
168+
}
169+
170+
public void setDescription(LocalizedString description) {
171+
this.description = description;
172+
}
173+
}
174+
175+
@Entity
176+
@Table(name = "CCM_OBJECTS")
177+
@Inheritance(strategy = InheritanceType.JOINED)
178+
public static class CcmObject implements Serializable {
179+
180+
private static final long serialVersionUID = 1L;
181+
182+
@Id
183+
@Column(name = "OBJECT_ID")
184+
@GeneratedValue(strategy = GenerationType.AUTO)
185+
private long objectId;
186+
187+
@Column(name = "DISPLAY_NAME")
188+
private String displayName;
189+
190+
@OneToMany(mappedBy = "categorizedObject", fetch = FetchType.LAZY)
191+
@OrderBy("categoryOrder ASC")
192+
private List<Categorization> categories;
193+
194+
public long getObjectId() {
195+
return objectId;
196+
}
197+
198+
public void setObjectId(long objectId) {
199+
this.objectId = objectId;
200+
}
201+
202+
public String getDisplayName() {
203+
return displayName;
204+
}
205+
206+
public void setDisplayName(String displayName) {
207+
this.displayName = displayName;
208+
}
209+
}
210+
211+
@Entity
212+
@Table(name = "CATEGORY_DOMAINS")
213+
public static class Domain extends CcmObject {
214+
215+
private static final long serialVersionUID = 1L;
216+
217+
@Column(name = "DOMAIN_KEY", nullable = false, unique = true, length = 255)
218+
private String domainKey;
219+
220+
@Embedded
221+
@AssociationOverride(
222+
name = "values",
223+
joinTable = @JoinTable(name = "DOMAIN_TITLES",
224+
joinColumns = {
225+
@JoinColumn(name = "OBJECT_ID")}))
226+
private LocalizedString title;
227+
228+
@Embedded
229+
@AssociationOverride(
230+
name = "values",
231+
joinTable = @JoinTable(name = "DOMAIN_DESCRIPTIONS",
232+
joinColumns = {
233+
@JoinColumn(name = "OBJECT_ID")}))
234+
private LocalizedString description;
235+
236+
public String getDomainKey() {
237+
return domainKey;
238+
}
239+
240+
public void setDomainKey(String domainKey) {
241+
this.domainKey = domainKey;
242+
}
243+
244+
public LocalizedString getTitle() {
245+
return title;
246+
}
247+
248+
public void setTitle(LocalizedString title) {
249+
this.title = title;
250+
}
251+
252+
public LocalizedString getDescription() {
253+
return description;
254+
}
255+
256+
public void setDescription(LocalizedString description) {
257+
this.description = description;
258+
}
259+
}
260+
261+
@Embeddable
262+
public static class LocalizedString implements Serializable {
263+
264+
private static final long serialVersionUID = 1L;
265+
266+
@ElementCollection(fetch = FetchType.EAGER)
267+
@MapKeyColumn(name = "LOCALE")
268+
@Column(name = "LOCALIZED_VALUE")
269+
@Lob
270+
@Type(type = "org.hibernate.type.TextType")
271+
private Map<Locale, String> values;
272+
273+
public LocalizedString() {
274+
values = new HashMap<>();
275+
}
276+
277+
public Map<Locale, String> getValues() {
278+
if (values == null) {
279+
return null;
280+
} else {
281+
return Collections.unmodifiableMap( values);
282+
}
283+
}
284+
285+
protected void setValues(final Map<Locale, String> values) {
286+
if (values == null) {
287+
this.values = new HashMap<>();
288+
} else {
289+
this.values = new HashMap<>(values);
290+
}
291+
}
292+
293+
public String getValue() {
294+
return getValue(Locale.getDefault());
295+
}
296+
297+
public String getValue(final Locale locale) {
298+
return values.get(locale);
299+
}
300+
301+
public void addValue(final Locale locale, final String value) {
302+
values.put(locale, value);
303+
}
304+
305+
public void removeValue(final Locale locale) {
306+
values.remove(locale);
307+
}
308+
309+
public boolean hasValue(final Locale locale) {
310+
return values.containsKey(locale);
311+
}
312+
313+
public Set<Locale> getAvailableLocales() {
314+
return values.keySet();
315+
}
316+
317+
}
318+
}

0 commit comments

Comments
 (0)