Skip to content

Commit 01f383f

Browse files
committed
HHH-18396 - Transform property-ref for one-to-one
1 parent 98e4bb9 commit 01f383f

File tree

13 files changed

+568
-37
lines changed

13 files changed

+568
-37
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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.boot.jaxb.hbm.transform;
8+
9+
import org.hibernate.mapping.Property;
10+
11+
/**
12+
* @author Steve Ebersole
13+
*/
14+
public class ColumnDefaultsProperty implements ColumnDefaults {
15+
private final Property property;
16+
17+
public ColumnDefaultsProperty(Property property) {
18+
this.property = property;
19+
}
20+
21+
@Override
22+
public Boolean isNullable() {
23+
return property.isOptional();
24+
}
25+
26+
@Override
27+
public Boolean isInsertable() {
28+
return property.isInsertable();
29+
}
30+
31+
@Override
32+
public Boolean isUpdateable() {
33+
return property.isUpdateable();
34+
}
35+
36+
@Override
37+
public Integer getLength() {
38+
return null;
39+
}
40+
41+
@Override
42+
public Integer getScale() {
43+
return null;
44+
}
45+
46+
@Override
47+
public Integer getPrecision() {
48+
return null;
49+
}
50+
51+
@Override
52+
public Boolean isUnique() {
53+
return Boolean.FALSE;
54+
}
55+
}

hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,20 +1173,27 @@ private void transferColumnsAndFormulas(
11731173
ColumnAndFormulaTarget target,
11741174
ColumnDefaults columnDefaults,
11751175
String table) {
1176-
for ( Selectable selectable : value.getSelectables() ) {
1176+
for ( int i = 0; i < value.getSelectables().size(); i++ ) {
1177+
final Selectable selectable = value.getSelectables().get( i );
11771178
if ( selectable instanceof Formula formula ) {
11781179
target.addFormula( formula.getFormula() );
11791180
}
11801181
else if ( selectable instanceof Column column ) {
11811182
final TargetColumnAdapter targetColumnAdapter = target.makeColumnAdapter( columnDefaults );
11821183
targetColumnAdapter.setName( column.getQuotedName() );
11831184
targetColumnAdapter.setTable( table );
1184-
// todo (7.0) : account for #insert, #update, etc
1185+
targetColumnAdapter.setLength( convertColumnLength( column.getLength() ) );
1186+
targetColumnAdapter.setPrecision( column.getPrecision() );
1187+
targetColumnAdapter.setScale( column.getScale() );
11851188
target.addColumn( targetColumnAdapter );
11861189
}
11871190
}
11881191
}
11891192

1193+
private Integer convertColumnLength(Long length) {
1194+
return length == null ? null : length.intValue();
1195+
}
1196+
11901197
private void transferColumnsAndFormulas(
11911198
ColumnAndFormulaSource source,
11921199
ColumnAndFormulaTarget target,
@@ -1709,10 +1716,9 @@ private void transferOneToOne(JaxbHbmOneToOneType hbmOneToOne, PropertyInfo prop
17091716
oneToOne.setOrphanRemoval( isOrphanRemoval( hbmOneToOne.getCascade() ) );
17101717
oneToOne.setForeignKey( new JaxbForeignKeyImpl() );
17111718
oneToOne.getForeignKey().setName( hbmOneToOne.getForeignKey() );
1712-
if (! StringHelper.isEmpty( hbmOneToOne.getPropertyRef() ) ) {
1713-
final JaxbJoinColumnImpl joinColumn = new JaxbJoinColumnImpl();
1714-
joinColumn.setReferencedColumnName( hbmOneToOne.getPropertyRef() );
1715-
oneToOne.getJoinColumnOrJoinFormula().add( joinColumn );
1719+
if ( StringHelper.isNotEmpty( hbmOneToOne.getPropertyRef() ) ) {
1720+
oneToOne.setPropertyRef( new JaxbPropertyRefImpl() );
1721+
oneToOne.getPropertyRef().setName( hbmOneToOne.getPropertyRef() );
17161722
}
17171723
for ( String formula : hbmOneToOne.getFormula() ) {
17181724
oneToOne.getJoinColumnOrJoinFormula().add( formula );
@@ -1780,7 +1786,7 @@ public void addFormula(String formula) {
17801786
jaxbManyToOne.getJoinColumnOrJoinFormula().add( formula );
17811787
}
17821788
},
1783-
ColumnDefaultsBasicImpl.INSTANCE,
1789+
new ColumnDefaultsProperty( manyToOneProperty ),
17841790
propertyInfo.tableName()
17851791
);
17861792

@@ -3001,7 +3007,7 @@ private void transferNonAggregatedCompositeId(
30013007
hbmCompositeId.getKeyPropertyOrKeyManyToOne().forEach( (hbmIdProperty) -> {
30023008
if ( hbmIdProperty instanceof JaxbHbmCompositeKeyBasicAttributeType hbmKeyProperty ) {
30033009
final PropertyInfo keyPropertyInfo = componentTypeInfo.propertyInfoMap().get( hbmKeyProperty.getName() );
3004-
mappingXmlEntity.getAttributes().getIdAttributes().add( transformNonAggregatedIdProperty(
3010+
mappingXmlEntity.getAttributes().getIdAttributes().add( transformNonAggregatedKeyProperty(
30053011
hbmKeyProperty,
30063012
keyPropertyInfo
30073013
) );
@@ -3022,7 +3028,7 @@ private void transferIdClass(
30223028
throw new UnsupportedOperationException( "Not implemented yet" );
30233029
}
30243030

3025-
private JaxbIdImpl transformNonAggregatedIdProperty(
3031+
private JaxbIdImpl transformNonAggregatedKeyProperty(
30263032
JaxbHbmCompositeKeyBasicAttributeType hbmIdProperty,
30273033
PropertyInfo idPropertyInfo) {
30283034
final JaxbIdImpl jaxbBasic = new JaxbIdImpl();
@@ -3058,7 +3064,8 @@ public String getFormulaAttribute() {
30583064

30593065
@Override
30603066
public List<Serializable> getColumnOrFormula() {
3061-
return Collections.emptyList();
3067+
//noinspection unchecked,rawtypes
3068+
return (List) hbmIdProperty.getColumn();
30623069
}
30633070

30643071
@Override

hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/OneToOneAttributeProcessing.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
package org.hibernate.boot.models.xml.internal.attr;
88

99
import org.hibernate.boot.jaxb.mapping.spi.JaxbOneToOneImpl;
10+
import org.hibernate.boot.models.HibernateAnnotations;
1011
import org.hibernate.boot.models.JpaAnnotations;
1112
import org.hibernate.boot.models.XmlAnnotations;
1213
import org.hibernate.boot.models.annotations.internal.OneToOneJpaAnnotation;
14+
import org.hibernate.boot.models.annotations.internal.PropertyRefAnnotation;
1315
import org.hibernate.boot.models.annotations.internal.TargetXmlAnnotation;
1416
import org.hibernate.boot.models.xml.internal.XmlProcessingHelper;
1517
import org.hibernate.boot.models.xml.internal.db.JoinColumnProcessing;
@@ -62,6 +64,14 @@ public static MutableMemberDetails processOneToOneAttribute(
6264
JoinColumnProcessing.applyJoinColumnsOrFormulas( jaxbOneToOne.getJoinColumnOrJoinFormula(), memberDetails, xmlDocumentContext );
6365
JoinColumnProcessing.applyPrimaryKeyJoinColumns( jaxbOneToOne.getPrimaryKeyJoinColumn(), memberDetails, xmlDocumentContext );
6466

67+
if ( jaxbOneToOne.getPropertyRef() != null ) {
68+
final PropertyRefAnnotation propertyRefUsage = (PropertyRefAnnotation) memberDetails.applyAnnotationUsage(
69+
HibernateAnnotations.PROPERTY_REF,
70+
xmlDocumentContext.getModelBuildingContext()
71+
);
72+
propertyRefUsage.value( jaxbOneToOne.getPropertyRef().getName() );
73+
}
74+
6575
if ( jaxbOneToOne.isId() == Boolean.TRUE ) {
6676
memberDetails.applyAnnotationUsage(
6777
JpaAnnotations.ID,

hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,11 +2092,14 @@
20922092
</xsd:sequence>
20932093
<xsd:sequence>
20942094
<xsd:sequence>
2095-
<xsd:choice maxOccurs="unbounded">
2096-
<xsd:element name="join-column" type="orm:join-column" minOccurs="0" maxOccurs="unbounded"/>
2097-
<xsd:element name="join-formula" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
2098-
</xsd:choice>
2099-
<xsd:element name="foreign-key" type="orm:foreign-key" minOccurs="0"/>
2095+
<xsd:sequence>
2096+
<xsd:choice maxOccurs="unbounded">
2097+
<xsd:element name="join-column" type="orm:join-column" minOccurs="0" maxOccurs="unbounded"/>
2098+
<xsd:element name="join-formula" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
2099+
</xsd:choice>
2100+
<xsd:element name="foreign-key" type="orm:foreign-key" minOccurs="0"/>
2101+
</xsd:sequence>
2102+
<xsd:element name="property-ref" type="orm:property-ref"/>
21002103
</xsd:sequence>
21012104
</xsd:sequence>
21022105
<xsd:element name="join-table" type="orm:join-table"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.orm.test.boot.models.hbm.foreigngenerator;
8+
9+
import org.hibernate.testing.orm.junit.DomainModel;
10+
import org.hibernate.testing.orm.junit.SessionFactory;
11+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
12+
import org.junit.jupiter.api.AfterEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
16+
17+
/**
18+
* @author Steve Ebersole
19+
*/
20+
@SuppressWarnings("JUnitMalformedDeclaration")
21+
@DomainModel(annotatedClasses = {Thing.class, Info.class})
22+
@SessionFactory
23+
public class ForeignGeneratorTests {
24+
@Test
25+
void checkGeneration(SessionFactoryScope sessionFactoryScope) {
26+
sessionFactoryScope.inTransaction( (session) -> {
27+
final Thing thing = new Thing( 1, "thing-1" );
28+
final Info info = new Info( thing, "info-1" );
29+
thing.setInfo( info );
30+
info.setOwner( thing );
31+
session.persist( thing );
32+
session.persist( info );
33+
} );
34+
35+
sessionFactoryScope.inTransaction( (session) -> {
36+
final Thing thing = session.find( Thing.class, 1 );
37+
assertThat( thing.getId() ).isEqualTo( thing.getInfo().getId() );
38+
} );
39+
}
40+
41+
@AfterEach
42+
void tearDown(SessionFactoryScope sessionFactoryScope) {
43+
sessionFactoryScope.inTransaction( (session) -> {
44+
session.createMutationQuery( "delete Info" ).executeUpdate();
45+
session.createMutationQuery( "delete Thing" ).executeUpdate();
46+
} );
47+
}
48+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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.orm.test.boot.models.hbm.foreigngenerator;
8+
9+
import org.hibernate.annotations.GenericGenerator;
10+
import org.hibernate.annotations.Parameter;
11+
import org.hibernate.id.ForeignGenerator;
12+
13+
import jakarta.persistence.Entity;
14+
import jakarta.persistence.GeneratedValue;
15+
import jakarta.persistence.Id;
16+
import jakarta.persistence.Basic;
17+
import jakarta.persistence.ManyToOne;
18+
import jakarta.persistence.OneToOne;
19+
20+
/**
21+
* @author Steve Ebersole
22+
*/
23+
@Entity
24+
public class Info {
25+
@Id
26+
@GeneratedValue( generator = "foreign" )
27+
@GenericGenerator(
28+
name = "foreign",
29+
type = ForeignGenerator.class,
30+
parameters = @Parameter( name = "property", value = "owner" )
31+
)
32+
private Integer id;
33+
@Basic
34+
private String name;
35+
36+
@ManyToOne
37+
private Thing owner;
38+
39+
protected Info() {
40+
// for Hibernate use
41+
}
42+
43+
public Info(Thing owner, String name) {
44+
this.owner = owner;
45+
this.name = name;
46+
}
47+
48+
public Integer getId() {
49+
return id;
50+
}
51+
52+
public String getName() {
53+
return name;
54+
}
55+
56+
public void setName(String name) {
57+
this.name = name;
58+
}
59+
60+
public Thing getOwner() {
61+
return owner;
62+
}
63+
64+
public void setOwner(Thing owner) {
65+
this.owner = owner;
66+
}
67+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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.orm.test.boot.models.hbm.foreigngenerator;
8+
9+
import jakarta.persistence.Entity;
10+
import jakarta.persistence.Id;
11+
import jakarta.persistence.Basic;
12+
import jakarta.persistence.OneToOne;
13+
import jakarta.persistence.SequenceGenerator;
14+
15+
/**
16+
* @author Steve Ebersole
17+
*/
18+
@Entity
19+
public class Thing {
20+
@Id
21+
private Integer id;
22+
@Basic
23+
private String name;
24+
@OneToOne(mappedBy = "owner")
25+
private Info info;
26+
27+
protected Thing() {
28+
// for Hibernate use
29+
}
30+
31+
public Thing(Integer id, String name) {
32+
this.id = id;
33+
this.name = name;
34+
}
35+
36+
public Integer getId() {
37+
return id;
38+
}
39+
40+
public String getName() {
41+
return name;
42+
}
43+
44+
public void setName(String name) {
45+
this.name = name;
46+
}
47+
48+
public Info getInfo() {
49+
return info;
50+
}
51+
52+
public void setInfo(Info info) {
53+
this.info = info;
54+
}
55+
}

0 commit comments

Comments
 (0)