Re: [hibernate-dev] HHH-13959 - OneToOne JoinTable with unique constraints work around?

"Jason Pyeron" <[email protected]>
Newsgroups gmane.comp.java.hibernate.devel
Message-ID <[email protected]>
[oops, did not mean to post the code to users]

I have narrowed it down, and I think these changes will address the issue.

commit 6ffdc4d684b33777b1c483473444d25b642e0748 (HEAD -> HHH-13959, pdinc-oss/HHH-13959)
Author: Jason Pyeron <[email protected]>
Date:   Mon Apr 20 02:20:21 2020 -0400

    HHH-13959 Added optional awareness to FK driven OneToOne mappings

    * PropertyBinder needed optional awareness, null means don't change/set it

diff --git a/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/AnnotationBinder.java b/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/AnnotationBinder.java
index eec3b49..392b8c6 100644
--- a/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/AnnotationBinder.java
+++ b/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/AnnotationBinder.java
@@ -3240,6 +3240,7 @@ public final class AnnotationBinder {
                }
                else {
                        //has a FK on the table
+                       propertyBinder.setOptional(optional);
                        bindManyToOne(
                                        cascadeStrategy, joinColumns, optional, ignoreNotFound, cascadeOnDelete,
                                        targetEntity,
diff --git a/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/annotations/PropertyBinder.java b/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/annotations/PropertyBinder.java
index 83c3f0c..e30946d 100644
--- a/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/annotations/PropertyBinder.java
+++ b/orm/hibernate-orm-5/src/test/java/org/hibernate/cfg/annotations/PropertyBinder.java
@@ -74,6 +74,17 @@ public class PropertyBinder {
        private EntityBinder entityBinder;
        private boolean isXToMany;
        private String referencedEntityName;
+       private Boolean optional;
+
+       public Boolean isOptional()
+       {
+               return optional;
+       }
+
+       public void setOptional(Boolean optional)
+       {
+               this.optional = optional;
+       }

        public void setReferencedEntityName(String referencedEntityName) {
                this.referencedEntityName = referencedEntityName;
@@ -328,6 +339,12 @@ public class PropertyBinder {

                LOG.tracev( "Cascading {0} with {1}", name, cascade );
                this.mappingProperty = prop;
+
+               if (optional != null)
+               {
+                   prop.setOptional(optional);
+               }
+
                return prop;
        }

-Jason

> -----Original Message-----
> From: [email protected] [mailto:[email protected]]
> On Behalf Of Jason Pyeron
> Sent: Monday, April 20, 2020 1:12 AM
> To: [email protected]; [email protected]
> Subject: Re: [hibernate-dev] HHH-13959 - OneToOne JoinTable with unique constraints work
> around?
> 
> [pardon the top post, it did not mix in well]
> 
> It looks like [stack trace 1] the option is never set in this situation, because the only
> place it is set is when
> 
> 		if ( trueOneToOne || mapToPK || !BinderHelper.isEmptyAnnotationValue( mappedBy )
> ) {
> 
> but since there is a FK involved it is running
> 
> 			//has a FK on the table
> 			bindManyToOne(
> 					cascadeStrategy, joinColumns, optional, ignoreNotFound,
> cascadeOnDelete,
> 					targetEntity,
> 					propertyHolder, inferredData, true, isIdentifierMapper,
> inSecondPass,
> 					propertyBinder, context
> 			);
> 
> Debugging shows the optional==true. Looking at that method, the only use of optional
> parameter is
> 
> 		if ( !optional ) {
> 			for ( Ejb3JoinColumn column : columns ) {
> 				column.setNullable( false );
> 			}
> 		}
> 
> Which is not relevant, since optional is true. That is the last line of code in
> bindOneToOne(...)
> 
> Now when the evaluation of the properties are being made to persist in the EntityMetamodel
> [stack trace 2] the optional is false. As a consequence the checkNullability(...) will
> fail with a PropertyValueException during the nullability check [stack trace 3]:
> 
> if ( !nullability[i] && value == null ) {
> 						//check basic level one nullablilty
> 						throw new PropertyValueException(
> 								"not-null property references a null or
> transient value",
> 								persister.getEntityName(),
> 								persister.getPropertyNames()[i]
> 							);
> 
> 					}
> 
> 1: 	AnnotationBinder.bindManyToOne(String, Ejb3JoinColumn[], boolean, boolean, boolean,
> XClass, PropertyHolder, PropertyData, boolean, boolean, boolean, PropertyBinder,
> MetadataBuildingContext) line: 3116
> 	AnnotationBinder.bindOneToOne(String, Ejb3JoinColumn[], boolean, FetchMode, boolean,
> boolean, XClass, PropertyHolder, PropertyData, String, boolean, boolean, boolean,
> PropertyBinder, MetadataBuildingContext) line: 3243
> 	AnnotationBinder.processElementAnnotations(PropertyHolder, Nullability, PropertyData,
> HashMap<String,IdentifierGeneratorDefinition>, EntityBinder, boolean, boolean, boolean,
> MetadataBuildingContext, Map<XClass,InheritanceState>) line: 1844
> 	AnnotationBinder.processIdPropertiesIfNotAlready(Map<XClass,InheritanceState>,
> MetadataBuildingContext, PersistentClass, EntityBinder, PropertyHolder,
> HashMap<String,IdentifierGeneratorDefinition>, ElementsToProcess, boolean, Set<String>)
> line: 975
> 	AnnotationBinder.bindClass(XClass, Map<XClass,InheritanceState>,
> MetadataBuildingContext) line: 802
> 	AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(Set<String>) line: 254
> 	MetadataBuildingProcess$1.processEntityHierarchies(Set<String>) line: 230
> 	MetadataBuildingProcess.complete(ManagedResources, BootstrapContext,
> MetadataBuildingOptions) line: 273
> 	EntityManagerFactoryBuilderImpl.metadata() line: 1214
> 	EntityManagerFactoryBuilderImpl.build() line: 1245
> 	HibernatePersistenceProvider.createEntityManagerFactory(String, Map) line: 56
> 	Persistence.createEntityManagerFactory(String, Map) line: 79
> 	Persistence.createEntityManagerFactory(String) line: 54
> 	JPAUnitTestCase.init() line: 27
> 
> 2: 	PropertyFactory.buildEntityBasedAttribute(EntityPersister, SessionFactoryImplementor,
> int, Property, boolean) line: 158
> 	EntityMetamodel.<init>(PersistentClass, EntityPersister, SessionFactoryImplementor)
> line: 224
> 	SingleTableEntityPersister(AbstractEntityPersister).<init>(PersistentClass,
> EntityDataAccess, NaturalIdDataAccess, PersisterCreationContext) line: 601
> 	SingleTableEntityPersister.<init>(PersistentClass, EntityDataAccess,
> NaturalIdDataAccess, PersisterCreationContext) line: 125
> 	NativeConstructorAccessorImpl.newInstance0(Constructor<?>, Object[]) line: not
> available [native method]
> 	NativeConstructorAccessorImpl.newInstance(Object[]) line: not available
> 	DelegatingConstructorAccessorImpl.newInstance(Object[]) line: not available
> 	Constructor<T>.newInstance(Object...) line: not available
> 	PersisterFactoryImpl.createEntityPersister(Class<EntityPersister>, PersistentClass,
> EntityDataAccess, NaturalIdDataAccess, PersisterCreationContext) line: 96
> 	PersisterFactoryImpl.createEntityPersister(PersistentClass, EntityDataAccess,
> NaturalIdDataAccess, PersisterCreationContext) line: 77
> 	MetamodelImpl.initialize(MetadataImplementor, JpaMetaModelPopulationSetting) line:
> 181
> 	SessionFactoryImpl.<init>(MetadataImplementor, SessionFactoryOptions) line: 299
> 	SessionFactoryBuilderImpl.build() line: 468
> 	EntityManagerFactoryBuilderImpl.build() line: 1249
> 	HibernatePersistenceProvider.createEntityManagerFactory(String, Map) line: 56
> 	Persistence.createEntityManagerFactory(String, Map) line: 79
> 	Persistence.createEntityManagerFactory(String) line: 54
> 	JPAUnitTestCase.init() line: 27
> 
> 3: 	Nullability.checkNullability(Object[], EntityPersister,
> Nullability$NullabilityCheckType) line: 92
> 	Nullability.checkNullability(Object[], EntityPersister, boolean) line: 55
> 	EntityIdentityInsertAction(AbstractEntityInsertAction).nullifyTransientReferencesIfNo
> tAlready() line: 116
> 	EntityIdentityInsertAction(AbstractEntityInsertAction).makeEntityManaged() line: 125
> 	ActionQueue.addResolvedEntityInsertAction(AbstractEntityInsertAction) line: 289
> 	ActionQueue.addInsertAction(AbstractEntityInsertAction) line: 263
> 	ActionQueue.addAction(EntityIdentityInsertAction) line: 317
> 	DefaultPersistEventListener(AbstractSaveEventListener).addInsertAction(Object[],
> Serializable, Object, EntityPersister, boolean, EventSource, boolean) line: 330
> 	DefaultPersistEventListener(AbstractSaveEventListener).performSaveOrReplicate(Object,
> EntityKey, EntityPersister, boolean, Object, EventSource, boolean) line: 287
> 	DefaultPersistEventListener(AbstractSaveEventListener).performSave(Object,
> Serializable, EntityPersister, boolean, Object, EventSource, boolean) line: 193
> 	DefaultPersistEventListener(AbstractSaveEventListener).saveWithGeneratedId(Object,
> String, Object, EventSource, boolean) line: 123
> 	DefaultPersistEventListener.entityIsTransient(PersistEvent, Map) line: 185
> 	DefaultPersistEventListener.onPersist(PersistEvent, Map) line: 128
> 	DefaultPersistEventListener.onPersist(PersistEvent) line: 55
> 	1021082377.accept(Object, Object) line: not available
> 	EventListenerGroupImpl<T>.fireEventOnEachListener(U, BiConsumer<T,U>) line: 102
> 	SessionImpl.firePersist(PersistEvent) line: 710
> 	SessionImpl.persist(Object) line: 696
> 	JPAUnitTestCase.hhh13959TestProfile() line: 43
> 
> > -----Original Message-----
> > From: [email protected] [mailto:hibernate-dev-
> [email protected]]
> > On Behalf Of Jason Pyeron
> > Sent: Sunday, April 19, 2020 11:18 PM
> > To: [email protected]; [email protected]
> > Subject: [hibernate-dev] HHH-13959 - OneToOne JoinTable with unique constraints work
> > around?
> >
> > https://hibernate.atlassian.net/browse/HHH-13959
> >
> >
> >
> > I started a DB migration today, now we are dead in the water due to this exception.
> >
> >
> >
> > When I persist an Entity on the owning side of the OneToOne(optional=true) relationship,
> > and that property is null we are getting:
> >
> >
> >
> > javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null
> > property references a null or transient value
> >
> >
> >
> > I am looking to where I can patch Hibernate or put a workaround in our code.
> >
> >
> >
> > Any help?
> >
> >
> >
> > -Jason
> >
> > _______________________________________________
> > hibernate-dev mailing list
> > [email protected]
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
> 
> 
> _______________________________________________
> hibernate-dev mailing list
> [email protected]
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.