HHH-4384 Allow join column override if @JoinColumn is absent on @OneToOne(mappedBy = "").

Tests: this case and disallow if mappedBy > "".
This commit is contained in:
Ptits de Barbe 2019-10-04 13:01:14 +03:00 committed by Christian Beikov
parent d998d6fb48
commit 19f6959519
2 changed files with 203 additions and 1 deletions

View File

@ -251,7 +251,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
String suffixForDefaultColumnName, String suffixForDefaultColumnName,
MetadataBuildingContext buildingContext) { MetadataBuildingContext buildingContext) {
if ( ann != null ) { if ( ann != null ) {
if ( BinderHelper.isEmptyAnnotationValue( mappedBy ) ) { if ( !BinderHelper.isEmptyOrNullAnnotationValue( mappedBy ) ) {
throw new AnnotationException( throw new AnnotationException(
"Illegal attempt to define a @JoinColumn with a mappedBy association: " "Illegal attempt to define a @JoinColumn with a mappedBy association: "
+ BinderHelper.getRelativePath( propertyHolder, propertyName ) + BinderHelper.getRelativePath( propertyHolder, propertyName )

View File

@ -0,0 +1,202 @@
package org.hibernate.orm.test.annotations.onetoone;
import java.util.Collection;
import java.util.Optional;
import org.hibernate.AnnotationException;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Table;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.BaseUnitTest;
import org.junit.jupiter.api.Test;
import jakarta.persistence.AssociationOverride;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.OneToOne;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Aresnii Skvortsov
*/
@TestForIssue(jiraKey = "HHH-4384")
@BaseUnitTest
public class OverrideOneToOneJoinColumnTest {
@Test
public void allowIfJoinColumnIsAbsent() {
try (StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build()) {
final Metadata metadata = new MetadataSources( ssr )
.addAnnotatedClass( Person.class )
.addAnnotatedClass( State.class )
.buildMetadata();
final Table personTable = metadata.getDatabase().getDefaultNamespace().locateTable(
Identifier.toIdentifier( "PERSON_TABLE" ) );
final Collection<ForeignKey> foreignKeys = personTable.getForeignKeys().values();
assertThat( foreignKeys.size(), is( 1 ) );
final Optional<ForeignKey> foreignKey = foreignKeys.stream().findFirst();
assertEquals(
"PERSON_ADDRESS_STATE",
foreignKey.get().getColumn( 0 ).getName(),
"Overridden join column name should be applied"
);
}
}
@Test
public void disallowOnSideWithMappedBy() {
try (StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build()) {
final AnnotationException ex = assertThrows(
AnnotationException.class, () ->
new MetadataSources( ssr )
.addAnnotatedClass( Employee.class )
.addAnnotatedClass( PartTimeEmployee.class )
.addAnnotatedClass( Desk.class )
.buildMetadata()
);
assertTrue(
ex.getMessage().startsWith( "Illegal attempt to define a @JoinColumn with a mappedBy association:" ),
"Should disallow exactly because of @JoinColumn override on side with mappedBy"
);
}
}
@Entity(name = "Person")
@jakarta.persistence.Table(name = "PERSON_TABLE")
public static class Person {
private String id;
private Address address;
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Embedded
@AssociationOverride(name = "state", joinColumns = { @JoinColumn(name = "PERSON_ADDRESS_STATE") })
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
@Embeddable
public static class Address {
private String street;
private String city;
private State state;
@OneToOne
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
@Entity(name = "State")
@jakarta.persistence.Table(name = "STATE_TABLE")
public static class State {
private String id;
private String name;
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@MappedSuperclass
public static class Employee {
@Id
private Long id;
private String name;
@OneToOne(mappedBy = "employee")
protected Desk desk;
}
@Entity
@AssociationOverride(name = "desk",
joinColumns = @JoinColumn(name = "PARTTIMEEMPLOYEE_DESK"))
public static class PartTimeEmployee extends Employee {
}
@Entity(name = "Desk")
public static class Desk {
@Id
private Long id;
@OneToOne
private PartTimeEmployee employee;
private String location;
}
}