I have an embeddable object YearModel that gets embedded into Impression which is itself an embeddable object. In Impression I map YearModel's columns to the correct names and mark all fields as allowing null. Finally, Impression is embedded in Lead.
Code:
@Embeddable
public class YearModel implements Serializable {
... fields: make, model, year, yearModelId ...
}
@Embeddable
public class Impression implements Serializable
{
...
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "make", column = @Column(name = "make_name", nullable = true)),
@AttributeOverride(name = "model", column = @Column(name = "model_name", nullable = true)),
@AttributeOverride(name = "year", column = @Column(name = "year_id", nullable = true)),
@AttributeOverride(name = "yearModelId", column = @Column(name = "year_model_id", nullable = true))
})
private YearModel yearModel;
...
}
@Entity
@Table(name = "lead")
public class Lead implements Serializable
{
...
@Embedded
private Impression impression = null;
...
}
This works fine as long as both impression and its yearModel are non-null. But when the lead inside the impression is null, I get a NPE when persisting the Lead:
Code:
org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.hgm.leads.model.YearModel.make org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:35)
org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:64)
org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:70)
org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:86)
org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:353)
org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:348)
org.hibernate.type.TypeFactory.replaceAssociations(TypeFactory.java:556)
org.hibernate.type.TypeFactory.replaceAssociations(TypeFactory.java:557)
org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:366)
org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:195)
org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener.entityIsTransient(IdTransferringMergeEventListener.java:59)
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
com.hgm.leads.dao.hibernate.LeadDaoHibernate.storeLead(LeadDaoHibernate.java:29)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
$Proxy56.storeLead(Unknown Source)
com.hgm.leads.LeadServiceImpl.createLead(LeadServiceImpl.java:58)
com.hgm.leads.LeadServiceAbstract.createLead(LeadServiceAbstract.java:20)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
$Proxy60.createLead(Unknown Source)
com.hgm.leads.http.CreateLeadServlet.testCreateLeadWithoutYearModel(CreateLeadServlet.java:65)
com.hgm.leads.http.CreateLeadServlet.doGet(CreateLeadServlet.java:33)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
root cause
java.lang.NullPointerException
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:36)
sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
java.lang.reflect.Field.get(Field.java:358)
org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:32)
org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:64)
org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:70)
org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:86)
org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:353)
org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:348)
org.hibernate.type.TypeFactory.replaceAssociations(TypeFactory.java:556)
org.hibernate.type.TypeFactory.replaceAssociations(TypeFactory.java:557)
org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:366)
org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:195)
org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener.entityIsTransient(IdTransferringMergeEventListener.java:59)
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:123)
org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:677)
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:661)
org.hibernate.impl.SessionImpl.merge(SessionImpl.java:665)
com.hgm.leads.dao.hibernate.LeadDaoHibernate.storeLead(LeadDaoHibernate.java:29)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
$Proxy56.storeLead(Unknown Source)
com.hgm.leads.LeadServiceImpl.createLead(LeadServiceImpl.java:58)
com.hgm.leads.LeadServiceAbstract.createLead(LeadServiceAbstract.java:20)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
$Proxy60.createLead(Unknown Source)
com.hgm.leads.http.CreateLeadServlet.testCreateLeadWithoutYearModel(CreateLeadServlet.java:65)
com.hgm.leads.http.CreateLeadServlet.doGet(CreateLeadServlet.java:33)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
Impression was originally an @Entity itself, but I could not get the @OneToOne association between it and Lead to work and embedded it inside Lead. Before that, YearModel worked fine embedded inside Impression even when it was null. The problem only arose once I changed Impression to be emdedded.
I tried copying the @AttributeOverrides from Impression to Lead and even prefixing their names with "yearModel." but no dice. It seems that Hibernate does not realize that all of YearModel's fields can be null and doesn't think to check if yearModel itself is null before accessing them.