StackOverflow during merge of pair of detached entities in JBoss EAP
Issue
- A "many to many" association (e.g. between
Employee
andTask
in the example below) is defined using an intermediate entity (e.g.TaskParticipant
in the example below). - The intermediate entity uses an {{@Embeddable}} (primary) key that maps a
ManyToOne}
association with both classes. - During merge of a detached entity on one side of the association (e.g.
Employee
), a non-terminating, recursive load loop is initiated resulting in an eventualjava.lang.StackOverflowError
. -
The repeating portion of the stack is shown below:
... java.lang.StackOverflowError ... at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1277) at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:1119) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:178) at org.hibernate.proxy.AbstractLazyInitializer.getIdentifier(AbstractLazyInitializer.java:89) at org.hibernate.type.EntityType.getHashCode(EntityType.java:372) at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:242) at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:61) at org.hibernate.engine.spi.EntityKey.<init>(EntityKey.java:54) at org.hibernate.internal.AbstractSharedSessionContract.generateEntityKey(AbstractSharedSessionContract.java:524) at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:879) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:729) at org.hibernate.loader.Loader.processResultSet(Loader.java:1002) at org.hibernate.loader.Loader.doQuery(Loader.java:960) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:351) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:321) at org.hibernate.loader.Loader.loadEntity(Loader.java:2379) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:64) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:54) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4289) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:597) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:565) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:226) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:122) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:93) ...
Source Code Example/Excerpt
@Entity
public class Employee {
@Id
private String name;
@OneToMany(mappedBy = "taskParticipantPK.employee", cascade = CascadeType.ALL, orphanRemoval = true)
private List<TaskParticipant> taskParticipants;
}
@Entity
public class Task {
@Id
private long id;
@OneToMany(mappedBy = "taskParticipantPK.task", cascade=CascadeType.ALL)
private List <TaskParticipant> taskParticipants;
}
@Entity
public class TaskParticipant {
@EmbeddedId
private TaskParticipantPK taskParticipantPK = new TaskParticipantPK();
}
@Embeddable
@Table(name = "TaskParticipant")
public class TaskParticipantPK implements Serializable {
private static final long serialVersionUID = 1;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employee")
private Employee employee;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "task")
private Task task;
}
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 7.3
- 7.2
- Hibernate 5.3
Subscriber exclusive content
A Red Hat subscription provides unlimited access to our knowledgebase, tools, and much more.