When attempting to delete an entity, a StackOverflowError
occurs. The only time this happens is when I have a composite key containing 2 foreign key references. I created a minimal example below:
First object containing a @OneToMany
collection:
@Entity
public class Foo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToMany(mappedBy = "id.foo", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Baz> baz;
// Getters and setters omitted.
}
Second object containing an @OneToMany
reference:
@Entity
public class Bar {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToMany(mappedBy = "id.bar", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Baz> baz;
// Getters and setters omitted.
}
Object containing both of the objects above (Foo
and Bar
) as a composite key:
@Entity
public class Baz {
@EmbeddedId
private BazId id;
// Getters and setters omitted.
}
And finally, the composite key class for Baz
:
@Embeddable
public class BazId implements Serializable {
private static final long serialVersionUID = -8869241450494423817L;
@ManyToOne
private Foo foo;
@ManyToOne
private Bar bar;
// Getters and setters omitted
}
When I perform the test below, I get a java.lang.StackOverflowError
:
// Spring Data JPA Repositories (extend CrudRepository)
@Autowired private FooRepository fooRepository;
@Autowired private BarRepository barRepository;
@Autowired private BazRepository bazRepository;
@Test
public void test() {
final Foo foo = new Foo();
fooRepository.save(foo);
final Bar bar = new Bar();
barRepository.save(bar);
final Baz baz = new Baz(new BazId(foo, bar));
bazRepository.save(baz);
foo.getBaz().add(baz);
bar.getBaz().add(baz);
// These two deletes cause the StackOverflowError
fooRepository.delete(foo);
barRepository.delete(bar);
}
What I've tried:
- Overriding
equals(Object o)
,toString()
, andhashCode()
.
I'm not sure what else to try other than redoing my mapping entirely. I need the mapping to be setup this way as in my real project, I have a User
following a Business
so this needs to be a composite key between two entities. Why is this causing infinite recursion?
EDIT
Stack trace if it helps (part of it. Whole thing wont fit):
java.lang.StackOverflowError
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:131)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
at com.sun.proxy.$Proxy73.prepareStatement(Unknown Source)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:146)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1929)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1898)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1876)
at org.hibernate.loader.Loader.doQuery(Loader.java:919)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:306)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2204)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:60)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:50)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:632)
at org.hibernate.type.EntityType.resolve(EntityType.java:424)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:848)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:714)
at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
at org.hibernate.loader.Loader.doQuery(Loader.java:930)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:306)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2204)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:60)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:50)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1022)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:632)
at org.hibernate.type.EntityType.resolve(EntityType.java:424)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:687)
at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:848)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:714)
at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
at org.hibernate.loader.Loader.doQuery(Loader.java:930)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)