I have a seemingly insurmountable issue with a compisite identifier. I think it might be a legitimate bug, and I'd like some opinions and ideas.
I have a legacy database that I must map objects against. I cannot modify the database structure. In that database, Enterprises are associated to Addresses with a join table.
This join table, ENT_ADDR, has 3 columns: "ENT_ID", "AD_ID", and "AD_TYPE". The AD_TYPE column is not a primary key, but instead identifies the nature of the address's association with the Enterprise. For instance, "Mailing", "Billing", "Physical".
Now, I need to map this in such a way that allows me to see the type of the address association, to that end, I created the following:
Code:
@Entity
@Table(name="ENTERPRISE")
public class Enterprise
{
@Id
@Column(name="EID")
private Long id = null;
@Column(name="NAME")
private String name = null;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="EID")
private Set<AddressAssociation> addresses = new HashSet<AddressAssociation>();
...
}
@Entity
@Table(name="ADDRESS")
public class Address
{
@Id
@Column(name="AID")
private Long id = null;
@Column(name="NAME")
private String name = null;
...
}
@Entity
@Table(name="ENT_ADDR")
@IdClass(AddressAssociation.class)
public class Address
{
@Id
private Enterprise enterprise;
@Id
private Address address;
@Column(name="AD_TYPE")
private String name = null;
...
}
@Embeddable
public class AddressAssociation
implements Serializable
{
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "ENT_ID", nullable = false)
private Enterprise enterprise = null;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "AD_ID", nullable = false)
private Address address = null;
...
}
Now, I realize that this isn't 100% JPA. But, the documentation for Hibernate Annotations says:
Quote:
While not supported by the EJB3 specification, Hibernate allows you to define associations inside a composite identifier. Simply use the regular annotations for that
I'm trying to store all brand new records. When I call EntityManager.persist(
I've tried this and several variations of it, but I always end up getting the Exception attached in the log.
Also, the following logging seems to show that it gets ID's from the DB for the Enterprise, but not for the Address.
Quote:
DEBUG nate.event.def.AbstractSaveEventListener - generated identifier: component[enterprise,address]{address=test.Address#null, enterprise=test.Enterprise#16475}, using strategy: org.hibernate.id.Assigned
DEBUG .event.def.AbstractFlushingEventListener - processing flush-time cascades
DEBUG nate.event.def.AbstractSaveEventListener - generated identifier: component[enterprise,address]{address=test.Address#null, enterprise=test.Enterprise#16475}, using strategy: org.hibernate.id.Assigned
Can anyone help?
For the record:
I'm using:
Hibernate Core 3.2.6.ga
Hibernate EntityManager 3.3.2
Hibernate Annotation 3.3.1
-------------------------------------------------
The Exception:
Quote:
javax.persistence.PersistenceException: java.lang.NullPointerException
at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:527)
at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:288)
at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:116)
at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:92)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:359)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
at test.Service$$EnhancerByCGLIB$$63761de3.createSource(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.mule.model.resolvers.AbstractEntryPointResolver.invokeMethod(AbstractEntryPointResolver.java:147)
at org.mule.model.resolvers.MethodHeaderPropertyEntryPointResolver.invoke(MethodHeaderPropertyEntryPointResolver.java:106)
at org.mule.model.resolvers.DefaultEntryPointResolverSet.invoke(DefaultEntryPointResolverSet.java:50)
at org.mule.component.DefaultLifecycleAdapter.intercept(DefaultLifecycleAdapter.java:202)
at org.mule.component.AbstractJavaComponent.invokeComponentInstance(AbstractJavaComponent.java:82)
at org.mule.component.AbstractJavaComponent.doOnCall(AbstractJavaComponent.java:73)
at org.mule.component.AbstractComponent.onCall(AbstractComponent.java:96)
at org.mule.model.seda.SedaService.doSend(SedaService.java:237)
at org.mule.service.AbstractService.sendEvent(AbstractService.java:510)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:354)
at org.mule.routing.inbound.DefaultInboundRouterCollection.send(DefaultInboundRouterCollection.java:221)
at org.mule.routing.inbound.DefaultInboundRouterCollection.route(DefaultInboundRouterCollection.java:181)
at org.mule.transport.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:604)
at org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:346)
at org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:269)
at org.mule.transport.vm.VMMessageReceiver.onCall(VMMessageReceiver.java:107)
at org.mule.transport.vm.VMMessageDispatcher$2.doInTransaction(VMMessageDispatcher.java:125)
at org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:99)
at org.mule.transport.vm.VMMessageDispatcher.doSend(VMMessageDispatcher.java:128)
at org.mule.transport.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:157)
at org.mule.transport.AbstractConnector.send(AbstractConnector.java:1889)
at org.mule.endpoint.DefaultOutboundEndpoint.send(DefaultOutboundEndpoint.java:76)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:327)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:213)
at org.mule.DefaultMuleEventContext.sendEvent(DefaultMuleEventContext.java:220)
at org.mule.module.client.remoting.RemoteDispatcherComponent.sendAction(RemoteDispatcherComponent.java:200)
at org.mule.module.client.remoting.RemoteDispatcherComponent.onCall(RemoteDispatcherComponent.java:110)
at org.mule.component.SimpleCallableJavaComponent.invokeComponentInstance(SimpleCallableJavaComponent.java:165)
at org.mule.component.AbstractJavaComponent.doOnCall(AbstractJavaComponent.java:73)
at org.mule.component.AbstractComponent.onCall(AbstractComponent.java:96)
at org.mule.model.seda.SedaService.doSend(SedaService.java:237)
at org.mule.service.AbstractService.sendEvent(AbstractService.java:510)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:354)
at org.mule.routing.inbound.DefaultInboundRouterCollection.send(DefaultInboundRouterCollection.java:221)
at org.mule.routing.inbound.DefaultInboundRouterCollection.route(DefaultInboundRouterCollection.java:181)
at org.mule.transport.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:604)
at org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:346)
at org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:287)
at org.mule.transport.http.HttpMessageReceiver$HttpWorker.doRequest(HttpMessageReceiver.java:271)
at org.mule.transport.http.HttpMessageReceiver$HttpWorker.processRequest(HttpMessageReceiver.java:229)
at org.mule.transport.http.HttpMessageReceiver$HttpWorker.run(HttpMessageReceiver.java:189)
at org.mule.work.WorkerContext.run(WorkerContext.java:310)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at org.hibernate.type.AbstractType.getHashCode(AbstractType.java:112)
at org.hibernate.type.AbstractType.getHashCode(AbstractType.java:120)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:279)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:189)
at org.hibernate.engine.EntityKey.generateHashCode(EntityKey.java:104)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:48)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:161)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:644)
at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:636)
at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:323)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:111)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:84)
at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:644)
at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:636)
at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:323)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:431)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:110)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:84)
at org.hibernate.impl.SessionImpl.firePersistOnFlush(SessionImpl.java:644)
at org.hibernate.impl.SessionImpl.persistOnFlush(SessionImpl.java:636)
at org.hibernate.engine.CascadingAction$9.cascade(CascadingAction.java:323)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:131)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:122)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:515)
... 60 more