The issue concerns a problem already signaled in different forums, and I decided to report it in JIRA, because many people have this same problem and after days and days of work around, the solutions possibles are heavy or dangerous for a database integrity (for example remove a non-nullability constraint...).
Here it is the problem a previous forum participant had perfectly summarized (see http://opensource.atlassian.com/projects/hibernate/browse/HHH-2326):
A null pointer exception is thrown when:
a) we have a composite key with one of the attributes of the key being an FK to another persistent class.
b) The other persistent class has an ID field whose value is being generated.
c) The instance of the other persistent class is transient (does not yet have an ID)
We do not get the null pointer if we explicitly set the ID (generator=assigned)
Here it is the failure trace:
-->
-->
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.engine.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:240)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:189)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:512)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:80)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:747)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:744)
at eu.cec.argus.bcm.dao.businessContinuityEvent.BusinessContinuityEventDAOImpl.createBCEvent(BusinessContinuityEventDAOImpl.java:39)
at eu.cec.argus.bcm.dao.businessContinuityEvent.BusinessContinuityEventDAOTest.testSaveBcEventAndRelatedMessagesAndMeetings(BusinessContinuityEventDAOTest.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:198)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:274)
at org.springframework.test.context.junit4.SpringMethodRoadie$2.run(SpringMethodRoadie.java:207)
at org.springframework.test.context.junit4.SpringMethodRoadie.runBeforesThenTestThenAfters(SpringMethodRoadie.java:254)
at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:234)
at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:204)
at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:146)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:151)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:26)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:36)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Here they are my classes:
@Entity
@Table(name = "BCM_BC_EVENT")
@IdClass(BusinessContinuityEvent.BusinessContinuityEventId.class)
@SequenceGenerator(name = "Generator.BusinessContinuityEvent", sequenceName = "SEQ_BCM_BC_EVENT")
public class BusinessContinuityEvent implements Serializable {
@Embeddable
public static class BusinessContinuityEventId implements Serializable {
private static final long serialVersionUID = 3513299649110908676L;
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Generator.BusinessContinuityEvent")
@Column(name = "BCE_ID", insertable = false, updatable = false, nullable = false)
private Long id;
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@JoinColumn(name = "EVE_ID", referencedColumnName = "EVE_ID", nullable = false)
private Event event;
public BusinessContinuityEventId(){
}
public BusinessContinuityEventId(Long id, Event event) {
this.id = id;
this.event = event;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BusinessContinuityEventId) {
BusinessContinuityEventId other = (BusinessContinuityEventId) obj;
return this.event.getId().equals(other.event.getId())
&& this.id.equals(other.id);
}
return false;
}
@Override
public int hashCode() {
return this.event.getId().hashCode() ^ this.id.hashCode();
}
}
private static final long serialVersionUID = 5385009048448590115L;
@Id
private Long id;
@Id
private Event event;
@OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@JoinColumns({
@JoinColumn(name = "BCE_ID", referencedColumnName = "BCE_ID"),
@JoinColumn(name = "EVE_ID", referencedColumnName = "EVE_ID")})
private List<Message> messages;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
}
Hibernate 3.25., Oracle 10g, Spring 2.5.5
I'm experiencing the same issue with Hibernate 3.3.1.GA (Part of JBoss 5.1.0.GA):
Project.java
Person.java
ProjectXPerson.java
My test case:
MTMTest.java
This test case fails with following exception:
If I remove comments from em.persist(joe); and em.persist(jane); lines it works as expected
In an effort to clean up, in bulk, tickets that are most likely out of date, we're transitioning all ORM 3 tickets to an "Awaiting Test Case" state. Please see http://in.relation.to/Bloggers/HibernateORMJIRAPoliciesAndCleanUpTactics for more information.
If this is still a legitimate bug in ORM 4, please provide either a test case that reproduces it or enough detail (entities, mappings, snippets, etc.) to show that it still fails on 4. If nothing is received within 3 months or so, we'll be automatically closing them.
Thank you!
Wow, 6 years passed since this blocker issue was created and it was never resolved.
Can anyone confirm that it's actually still an issue in ORM 4?
Bulk rejecting stale issues. If this is still a legitimate issue on ORM 4, feel free to comment and attach a test case. I'll address responses case-by-case. Thanks!