Skip to content

Commit 19f6959

Browse files
ettavoltbeikov
authored andcommitted
HHH-4384 Allow join column override if @joincolumn is absent on @OnetoOne(mappedBy = "").
Tests: this case and disallow if mappedBy > "".
1 parent d998d6f commit 19f6959

File tree

2 files changed

+203
-1
lines changed

2 files changed

+203
-1
lines changed

hibernate-core/src/main/java/org/hibernate/cfg/AnnotatedJoinColumn.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ private static AnnotatedJoinColumn buildJoinColumn(
251251
String suffixForDefaultColumnName,
252252
MetadataBuildingContext buildingContext) {
253253
if ( ann != null ) {
254-
if ( BinderHelper.isEmptyAnnotationValue( mappedBy ) ) {
254+
if ( !BinderHelper.isEmptyOrNullAnnotationValue( mappedBy ) ) {
255255
throw new AnnotationException(
256256
"Illegal attempt to define a @JoinColumn with a mappedBy association: "
257257
+ BinderHelper.getRelativePath( propertyHolder, propertyName )
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package org.hibernate.orm.test.annotations.onetoone;
2+
3+
import java.util.Collection;
4+
import java.util.Optional;
5+
6+
import org.hibernate.AnnotationException;
7+
import org.hibernate.boot.Metadata;
8+
import org.hibernate.boot.MetadataSources;
9+
import org.hibernate.boot.model.naming.Identifier;
10+
import org.hibernate.boot.registry.StandardServiceRegistry;
11+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
12+
import org.hibernate.mapping.ForeignKey;
13+
import org.hibernate.mapping.Table;
14+
15+
import org.hibernate.testing.TestForIssue;
16+
import org.hibernate.testing.orm.junit.BaseUnitTest;
17+
import org.junit.jupiter.api.Test;
18+
19+
import jakarta.persistence.AssociationOverride;
20+
import jakarta.persistence.Embeddable;
21+
import jakarta.persistence.Embedded;
22+
import jakarta.persistence.Entity;
23+
import jakarta.persistence.Id;
24+
import jakarta.persistence.JoinColumn;
25+
import jakarta.persistence.MappedSuperclass;
26+
import jakarta.persistence.OneToOne;
27+
28+
import static org.hamcrest.MatcherAssert.assertThat;
29+
import static org.hamcrest.Matchers.is;
30+
import static org.junit.jupiter.api.Assertions.assertEquals;
31+
import static org.junit.jupiter.api.Assertions.assertThrows;
32+
import static org.junit.jupiter.api.Assertions.assertTrue;
33+
34+
/**
35+
* @author Aresnii Skvortsov
36+
*/
37+
@TestForIssue(jiraKey = "HHH-4384")
38+
@BaseUnitTest
39+
public class OverrideOneToOneJoinColumnTest {
40+
41+
@Test
42+
public void allowIfJoinColumnIsAbsent() {
43+
try (StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build()) {
44+
final Metadata metadata = new MetadataSources( ssr )
45+
.addAnnotatedClass( Person.class )
46+
.addAnnotatedClass( State.class )
47+
.buildMetadata();
48+
49+
final Table personTable = metadata.getDatabase().getDefaultNamespace().locateTable(
50+
Identifier.toIdentifier( "PERSON_TABLE" ) );
51+
final Collection<ForeignKey> foreignKeys = personTable.getForeignKeys().values();
52+
assertThat( foreignKeys.size(), is( 1 ) );
53+
final Optional<ForeignKey> foreignKey = foreignKeys.stream().findFirst();
54+
55+
assertEquals(
56+
"PERSON_ADDRESS_STATE",
57+
foreignKey.get().getColumn( 0 ).getName(),
58+
"Overridden join column name should be applied"
59+
);
60+
}
61+
}
62+
63+
@Test
64+
public void disallowOnSideWithMappedBy() {
65+
try (StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build()) {
66+
final AnnotationException ex = assertThrows(
67+
AnnotationException.class, () ->
68+
new MetadataSources( ssr )
69+
.addAnnotatedClass( Employee.class )
70+
.addAnnotatedClass( PartTimeEmployee.class )
71+
.addAnnotatedClass( Desk.class )
72+
.buildMetadata()
73+
);
74+
75+
assertTrue(
76+
ex.getMessage().startsWith( "Illegal attempt to define a @JoinColumn with a mappedBy association:" ),
77+
"Should disallow exactly because of @JoinColumn override on side with mappedBy"
78+
);
79+
}
80+
}
81+
82+
@Entity(name = "Person")
83+
@jakarta.persistence.Table(name = "PERSON_TABLE")
84+
public static class Person {
85+
86+
private String id;
87+
88+
private Address address;
89+
90+
@Id
91+
public String getId() {
92+
return id;
93+
}
94+
95+
public void setId(String id) {
96+
this.id = id;
97+
}
98+
99+
@Embedded
100+
@AssociationOverride(name = "state", joinColumns = { @JoinColumn(name = "PERSON_ADDRESS_STATE") })
101+
public Address getAddress() {
102+
return address;
103+
}
104+
105+
public void setAddress(Address address) {
106+
this.address = address;
107+
}
108+
}
109+
110+
@Embeddable
111+
public static class Address {
112+
113+
private String street;
114+
115+
private String city;
116+
117+
private State state;
118+
119+
@OneToOne
120+
public State getState() {
121+
return state;
122+
}
123+
124+
public void setState(State state) {
125+
this.state = state;
126+
}
127+
128+
public String getStreet() {
129+
return street;
130+
}
131+
132+
public void setStreet(String street) {
133+
this.street = street;
134+
}
135+
136+
public String getCity() {
137+
return city;
138+
}
139+
140+
public void setCity(String city) {
141+
this.city = city;
142+
}
143+
}
144+
145+
@Entity(name = "State")
146+
@jakarta.persistence.Table(name = "STATE_TABLE")
147+
public static class State {
148+
149+
private String id;
150+
151+
private String name;
152+
153+
@Id
154+
public String getId() {
155+
return id;
156+
}
157+
158+
public void setId(String id) {
159+
this.id = id;
160+
}
161+
162+
public String getName() {
163+
return name;
164+
}
165+
166+
public void setName(String name) {
167+
this.name = name;
168+
}
169+
}
170+
171+
@MappedSuperclass
172+
public static class Employee {
173+
174+
@Id
175+
private Long id;
176+
177+
private String name;
178+
179+
@OneToOne(mappedBy = "employee")
180+
protected Desk desk;
181+
}
182+
183+
@Entity
184+
@AssociationOverride(name = "desk",
185+
joinColumns = @JoinColumn(name = "PARTTIMEEMPLOYEE_DESK"))
186+
public static class PartTimeEmployee extends Employee {
187+
188+
}
189+
190+
@Entity(name = "Desk")
191+
public static class Desk {
192+
@Id
193+
private Long id;
194+
195+
@OneToOne
196+
private PartTimeEmployee employee;
197+
198+
private String location;
199+
}
200+
201+
202+
}

0 commit comments

Comments
 (0)