I have a Customer entity that is outlined like this:
@Entity
public class Customer {
...
@Embedded()
private Address postalAddress;
...
The Address Embeddable looks like this:
@Embeddable
public class Address implements Serializable {
@Basic
@Size(max = 50)
private String address1;
@Basic
@Size(max = 50)
private String address2;
@Basic
@Size(max = 50)
private String address3;
@Basic
@Size(max = 50)
private String city;
@Basic
@Size(max = 10)
private String postalCode;
public Address() {
super();
}
public Address(final String address1, final String address2, final String address3, final String city,
final String postalCode) {
this();
setAddress1(address1);
setAddress2(address2);
setAddress3(address3);
setCity(city);
setPostalCode(postalCode);
}
...
}
Now, if I Hibernate loads a Customer entity from the Database where all the address fields are null, it will set the postalAddress address reference in the resulting Customer Object also to null, which I think is correct. In general this null postalAddress reference doesn't cause any issue. However, things start going wrong if I set enableDirtyTracking to true in gradle like this:
hibernate {
enhancement {
enableLazyInitialization = false
enableDirtyTracking = true
enableAssociationManagement = false
enableExtendedEnhancement = false
}
}
With such a setup, as soon as Hibernate tries load a customer that have a resulting null postalAddress reference, I get the following exception:
Caused by: java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.spi.CompositeTracker.$$_hibernate_setOwner(String, org.hibernate.engine.spi.CompositeOwner)" because "value" is null
at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final at org.hibernate@6.1.5.Final
I had a look at the source code of EnhancedSetterImpl.java, where the exception occurs, which I have outlined below. If I have enabled enableDirtyTracking, then it does go into the first if statement shown. In such a case value will be null for postalAddress and will cause the NullpointerException. I belief this should be a bug in how enableDirtyTracking works, since it does works fine if I don't enable this. I have tried the same with 6.1.6 by getting the source from Github and compiling it, but I get the same error.
@Override
public void set(Object target, Object value) {
super.set( target, value );
if ( ( enhancementState & COMPOSITE_OWNER ) != 0 && ( ( enhancementState & COMPOSITE_TRACKER_MASK ) != 0 || value instanceof CompositeTracker ) ) {
( (CompositeTracker) value ).$$_hibernate_setOwner( propertyName, (CompositeOwner) target );
}
if ( ( enhancementState & PERSISTENT_ATTRIBUTE_INTERCEPTABLE_MASK ) != 0 ) {
final PersistentAttributeInterceptable asPersistentAttributeInterceptable = ManagedTypeHelper.asPersistentAttributeInterceptable(
target );
PersistentAttributeInterceptor interceptor = asPersistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( interceptor instanceof BytecodeLazyAttributeInterceptor ) {
( (BytecodeLazyAttributeInterceptor) interceptor ).attributeInitialized( propertyName );
}
}
}
|