44 */
55package org .hibernate .boot .model .internal ;
66
7- import java .util .EnumSet ;
87import java .util .Map ;
98
109import org .hibernate .AnnotationException ;
1110import org .hibernate .MappingException ;
12- import org .hibernate .annotations .CascadeType ;
13- import org .hibernate .annotations .LazyGroup ;
1411import org .hibernate .annotations .NotFoundAction ;
15- import org .hibernate .annotations .OnDeleteAction ;
1612import org .hibernate .boot .spi .MetadataBuildingContext ;
1713import org .hibernate .boot .spi .PropertyData ;
1814import org .hibernate .boot .spi .SecondPass ;
2420import org .hibernate .mapping .PersistentClass ;
2521import org .hibernate .mapping .Property ;
2622import org .hibernate .mapping .SortableValue ;
27- import org .hibernate .models .spi .MemberDetails ;
28- import org .hibernate .type .ForeignKeyDirection ;
29-
30- import jakarta .persistence .ForeignKey ;
3123
3224import static org .hibernate .boot .model .internal .BinderHelper .checkMappedByType ;
3325import static org .hibernate .boot .model .internal .BinderHelper .findPropertyByName ;
3426import static org .hibernate .boot .model .internal .BinderHelper .getPath ;
35- import static org .hibernate .boot .model .internal .ToOneBinder .bindForeignKeyNameAndDefinition ;
36- import static org .hibernate .boot .model .internal .ToOneBinder .defineFetchingStrategy ;
3727import static org .hibernate .internal .util .StringHelper .qualify ;
38- import static org .hibernate .type .ForeignKeyDirection .FROM_PARENT ;
39- import static org .hibernate .type .ForeignKeyDirection .TO_PARENT ;
4028
4129/**
4230 * We have to handle {@link jakarta.persistence.OneToOne} associations
4533public class OneToOneSecondPass implements SecondPass {
4634 private final PropertyData inferredData ;
4735 private final PropertyHolder propertyHolder ;
36+ private final OneToOne oneToOne ;
37+ private final PropertyBinder binder ;
38+ private final Property property ;
4839 private final String mappedBy ;
4940 private final String ownerEntity ;
5041 private final NotFoundAction notFoundAction ;
51- private final OnDeleteAction onDeleteAction ;
52- private final boolean optional ;
53- private final EnumSet <CascadeType > cascadeStrategy ;
5442 private final AnnotatedJoinColumns joinColumns ;
5543 private final MetadataBuildingContext buildingContext ;
56- private final String referencedEntityName ;
5744 private final boolean annotatedEntity ;
5845
5946 public OneToOneSecondPass (
47+ PropertyBinder binder ,
48+ Property property ,
49+ OneToOne oneToOne ,
6050 String mappedBy ,
6151 String ownerEntity ,
6252 PropertyHolder propertyHolder ,
6353 PropertyData inferredData ,
64- String referencedEntityName ,
6554 boolean annotatedEntity ,
6655 NotFoundAction notFoundAction ,
67- OnDeleteAction onDeleteAction ,
68- boolean optional ,
69- EnumSet <CascadeType > cascadeStrategy ,
7056 AnnotatedJoinColumns columns ,
7157 MetadataBuildingContext buildingContext ) {
58+ this .binder = binder ;
59+ this .property = property ;
60+ this .oneToOne = oneToOne ;
7261 this .ownerEntity = ownerEntity ;
7362 this .mappedBy = mappedBy ;
7463 this .propertyHolder = propertyHolder ;
75- this .referencedEntityName = referencedEntityName ;
7664 this .buildingContext = buildingContext ;
7765 this .notFoundAction = notFoundAction ;
7866 this .inferredData = inferredData ;
7967 this .annotatedEntity = annotatedEntity ;
80- this .onDeleteAction = onDeleteAction ;
81- this .optional = optional ;
82- this .cascadeStrategy = cascadeStrategy ;
8368 this .joinColumns = columns ;
8469 }
8570
8671 @ Override
8772 public void doSecondPass (Map <String , PersistentClass > persistentClasses ) throws MappingException {
88- final var oneToOne =
89- new OneToOne ( buildingContext , propertyHolder .getTable (),
90- propertyHolder .getPersistentClass () );
91- final String propertyName = inferredData .getPropertyName ();
92- oneToOne .setPropertyName ( propertyName );
93- oneToOne .setReferencedEntityName ( referencedEntityName );
94- MemberDetails property = inferredData .getAttributeMember ();
95- defineFetchingStrategy ( oneToOne , property , inferredData , propertyHolder );
96- //value.setFetchMode( fetchMode );
97- oneToOne .setOnDeleteAction ( onDeleteAction );
98- //value.setLazy( fetchMode != FetchMode.JOIN );
99-
100- oneToOne .setConstrained ( !optional );
101- oneToOne .setForeignKeyType ( getForeignKeyDirection () );
102- bindForeignKeyNameAndDefinition ( oneToOne , property ,
103- property .getDirectAnnotationUsage ( ForeignKey .class ),
104- buildingContext );
105-
106- final var binder = new PropertyBinder ();
107- binder .setName ( propertyName );
108- binder .setMemberDetails ( property );
109- binder .setValue ( oneToOne );
110- binder .setCascade ( cascadeStrategy );
111- binder .setAccessType ( inferredData .getDefaultAccess () );
112- binder .setBuildingContext ( buildingContext );
113- binder .setHolder ( propertyHolder );
114-
115- final var lazyGroupAnnotation = property .getDirectAnnotationUsage ( LazyGroup .class );
116- if ( lazyGroupAnnotation != null ) {
117- binder .setLazyGroup ( lazyGroupAnnotation .value () );
118- }
119-
120- final Property result = binder .makeProperty ();
121- result .setOptional ( optional );
12273 if ( mappedBy == null ) {
123- bindOwned ( persistentClasses , oneToOne , propertyName , result );
74+ bindOwned ( persistentClasses , oneToOne , inferredData . getPropertyName () );
12475 }
12576 else {
126- bindUnowned ( persistentClasses , oneToOne , result );
77+ bindUnowned ( persistentClasses , oneToOne );
12778 }
128- binder .callAttributeBindersInSecondPass ( result );
79+ binder .callAttributeBindersInSecondPass ( property );
12980 oneToOne .sortProperties ();
13081 }
13182
132- private ForeignKeyDirection getForeignKeyDirection () {
133- return mappedBy == null ? FROM_PARENT : TO_PARENT ;
134- }
135-
136- private void bindUnowned (Map <String , PersistentClass > persistentClasses , OneToOne oneToOne , Property property ) {
83+ private void bindUnowned (Map <String , PersistentClass > persistentClasses , OneToOne oneToOne ) {
13784 oneToOne .setMappedByProperty ( mappedBy );
13885 final String targetEntityName = oneToOne .getReferencedEntityName ();
13986 final var targetEntity = persistentClasses .get ( targetEntityName );
@@ -146,13 +93,10 @@ private void bindUnowned(Map<String, PersistentClass> persistentClasses, OneToOn
14693 }
14794 final var targetProperty = targetProperty ( oneToOne , targetEntity );
14895 final var targetPropertyValue = targetProperty .getValue ();
149- if ( targetPropertyValue instanceof OneToOne ) {
150- propertyHolder . addProperty ( property , inferredData . getAttributeMember (), inferredData . getDeclaringClass () );
96+ if ( targetPropertyValue instanceof ManyToOne ) {
97+ bindTargetManyToOne ( persistentClasses , oneToOne , targetEntity , targetProperty );
15198 }
152- else if ( targetPropertyValue instanceof ManyToOne ) {
153- bindTargetManyToOne ( persistentClasses , oneToOne , property , targetEntity , targetProperty );
154- }
155- else {
99+ else if ( !(targetPropertyValue instanceof OneToOne ) ) {
156100 throw new AnnotationException ( "Association '" + getPath ( propertyHolder , inferredData )
157101 + "' is 'mappedBy' a property named '" + mappedBy
158102 + "' of the target entity type '" + targetEntityName
@@ -170,7 +114,6 @@ else if ( targetPropertyValue instanceof ManyToOne ) {
170114 private void bindTargetManyToOne (
171115 Map <String , PersistentClass > persistentClasses ,
172116 OneToOne oneToOne ,
173- Property property ,
174117 PersistentClass targetEntity ,
175118 Property targetProperty ) {
176119 Join otherSideJoin = null ;
@@ -192,10 +135,9 @@ private void bindTargetManyToOne(
192135 copy .setValue ( manyToOne );
193136 manyToOne .addColumn ( copy );
194137 }
195- mappedByJoin .addProperty ( property );
196- }
197- else {
198- propertyHolder .addProperty ( property , inferredData .getAttributeMember (), inferredData .getDeclaringClass () );
138+ // The property was added to the propertyHolder eagerly to have knowledge about this property,
139+ // in order for de-duplication to kick in, but we move it to a join if necessary
140+ propertyHolder .movePropertyToJoin ( property , mappedByJoin , inferredData .getAttributeMember (), inferredData .getDeclaringClass () );
199141 }
200142
201143 oneToOne .setReferencedPropertyName ( mappedBy );
@@ -246,8 +188,7 @@ private Property targetProperty(OneToOne oneToOne, PersistentClass targetEntity)
246188 private void bindOwned (
247189 Map <String , PersistentClass > persistentClasses ,
248190 OneToOne oneToOne ,
249- String propertyName ,
250- Property property ) {
191+ String propertyName ) {
251192 final ToOneFkSecondPass secondPass = new ToOneFkSecondPass (
252193 oneToOne ,
253194 joinColumns ,
@@ -259,7 +200,6 @@ private void bindOwned(
259200 );
260201 secondPass .doSecondPass (persistentClasses );
261202 //no column associated since it's a one to one
262- propertyHolder .addProperty ( property , inferredData .getAttributeMember (), inferredData .getDeclaringClass () );
263203 }
264204
265205 /**
0 commit comments