Null pointer exception on org.hibernate.type.AbstractType.getHashCode(AbstractType.java:112)

Description

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;
}

}

Environment

Hibernate 3.25., Oracle 10g, Spring 2.5.5

Activity

Show:
Dmitry Bedrin
August 14, 2012, 7:22 PM

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

Brett Meyer
April 8, 2014, 3:46 AM

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!

Roberto Lavarreda
April 9, 2014, 6:40 AM

Wow, 6 years passed since this blocker issue was created and it was never resolved.

Brett Meyer
April 9, 2014, 6:49 AM

Can anyone confirm that it's actually still an issue in ORM 4?

Brett Meyer
July 9, 2014, 1:11 AM

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!

Rejected

Assignee

Unassigned

Reporter

DEROUET

Fix versions

None

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

Priority

Blocker