1

Can someone explain, how this should actually be accomplished?

I have a Parent entity (called Executor in the bottom stack trace):

class Parent {
   @Id
   private int id;
}

and I have a Child (Param1CK in the stack trace, params3 table), which's Id is Composite, and relies on the "Parent" and a "line number":

@IdClass(ChildID.class)
class Child {
   @Id
   @ManyToOne
   @JoinColumn
   private Parent parent;

   @Id
   @Column
   private int id;
}

class ChildID implements Serializable{
  private Parent parent;
  private int id;

  @Override
  public int hashCode() {...}
}

The collection of Child in parent is described as:

   @OneToMany(mappedBy="parent")
   @Cascasde(value = CascadeType.ALL)
   private List<Child> list = ...;

And this point seems to be resolved incorrectly.

When I try to do a:

Parent p = new Parent();
p.getList().add(new Child(p)); // with the Parent targeting in the constructor

and do a multiple "save" operation, Hibernate fails to resolve the key, and does a loop for resolving the parent key, which is resolving to stackOverFlow:

Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
Hibernate: select executor0_.id as id1_3_1_, executor0_.parent_id as parent_i2_3_1_, params3x1_.parent_id as parent_i3_6_3_, params3x1_.prop as prop1_6_3_, params3x1_.prop as prop1_6_0_, params3x1_.parent_id as parent_i3_6_0_, params3x1_.value as value2_6_0_ from executor executor0_ left outer join paraaaamsssck params3x1_ on executor0_.id=params3x1_.parent_id where executor0_.id=?
2019-04-19 11:05:19 WARN  [localhost-startStop-1] AnnotationConfigServletWebServerApplicationContext.refresh: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fixingTheSessionCrapService': Invocation of init method failed; nested exception is java.lang.StackOverflowError
2019-04-19 11:05:19 INFO  [localhost-startStop-1] ExecutorService.killRunningSessions: Killing any running sessions
2019-04-19 11:05:19 INFO  [localhost-startStop-1] ExecutorService.killRunningSessions: Done. ATA closed gracefully
2019-04-19 11:05:19 INFO  [localhost-startStop-1] ThreadPoolTaskExecutor.shutdown: Shutting down ExecutorService 'getDaemonThreadPool'
2019-04-19 11:05:19 INFO  [localhost-startStop-1] LocalContainerEntityManagerFactoryBean.destroy: Closing JPA EntityManagerFactory for persistence unit 'default'
2019-04-19 11:05:19 INFO  [localhost-startStop-1] HikariDataSource.close: HikariPool-1 - Shutdown initiated...
2019-04-19 11:05:19 INFO  [localhost-startStop-1] HikariDataSource.close: HikariPool-1 - Shutdown completed.
2019-04-19 11:05:19 INFO  [localhost-startStop-1] ConditionEvaluationReportLoggingListener.logMessage: 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-04-19 11:05:19 ERROR [localhost-startStop-1] SpringApplication.reportFailure: Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fixingTheSessionCrapService': Invocation of init method failed; nested exception is java.lang.StackOverflowError
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:414)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5245)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1420)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1410)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.StackOverflowError: null
    at java.base/java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:578)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:292)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:281)
    at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
    at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:211)
    at java.base/java.io.BufferedWriter.flushBuffer(BufferedWriter.java:120)
    at java.base/java.io.PrintStream.write(PrintStream.java:526)
    at java.base/java.io.PrintStream.print(PrintStream.java:666)
    at java.base/java.io.PrintStream.println(PrintStream.java:803)
    at org.apache.tomcat.util.log.SystemLogHandler.println(SystemLogHandler.java:267)
    at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:96)
    at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:78)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:167)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:148)
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1984)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1914)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1892)
    at org.hibernate.loader.Loader.doQuery(Loader.java:937)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:310)
    at org.hibernate.loader.Loader.loadEntity(Loader.java:2281)
    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:4271)
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:511)
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:481)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:222)
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:281)
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:124)
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:92)
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1256)
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1139)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:682)
    at org.hibernate.type.EntityType.resolve(EntityType.java:464)
    at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:239)
    at org.hibernate.type.EntityType.resolve(EntityType.java:457)
    at org.hibernate.type.ComponentType.resolve(ComponentType.java:688)
    at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:862)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:718)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:990)
    at org.hibernate.loader.Loader.doQuery(Loader.java:948)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:310)
    at org.hibernate.loader.Loader.loadEntity(Loader.java:2281)
    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:4271)
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:511)
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:481)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:222)
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:281)
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:124)
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:92)

And this goes a long looped way till a StackOverflow exception appears. At the end it states:

at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1256)
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1139)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:682)
    at org.hibernate.type.EntityType.resolve(EntityType.java:464)
    at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:239)
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
Draaksward
  • 759
  • 7
  • 32

2 Answers2

1

1) Make you id class Embeddable as you have a ManyToOne relation as part of the id:

@Embeddable
class ChildID implements Serializable{

  @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  @JoinColumn(name = "parent_id")
  private Parent parent;
  private int id;

2) Alter the Child class:

@Entity
class Child {

   @EmbeddedId
   private ChildID id;

3) Alter the mappedBy on the Parent entity to take into consideration the embedded relation:

   @OneToMany(mappedBy="id.parent")
   @Cascasde(value = CascadeType.ALL)
   private List<Child> list = ...;
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • Tried this. No, still the same. – Draaksward Apr 19 '19 at 09:27
  • Still the stackOverFlow. I've managed to find a solution, going by this example - https://stackoverflow.com/questions/31385658/jpa-how-to-make-composite-foreign-key-part-of-composite-primary-key – Draaksward Apr 19 '19 at 09:33
0

If someone stumbles on this (or until a better solution will be stated), here is what actually worked for me (I do apologize for the eye burning class and element naming, have been trying this for the last few days). Taken from the @OneToMany and composite primary keys?

@Entity
@Table(name = "paraaaamsssCK")
public class Param1CK {
    @EmbeddedId
    private Param1CKEmbeddable key;

    @Column(name = "value")
    private String value;

    @MapsId("parentId")
    @ManyToOne
    @JoinColumn
    public Executor parent;


    public Param1CK() {
        super();
    }



    public Param1CK(Executor parent, String id, String value) {
        key = new Param1CKEmbeddable(id);
        this.parent = parent;
        this.value = value;
    }
}

Here's the Embeddable definition:

@Embeddable
public class Param1CKEmbeddable implements Serializable{
    private int parentId;
    private String id;

public Param1CKEmbeddable() { }

public Param1CKEmbeddable(int parentId, String id) {
    this.parentId = parentId;
    this.id = id;
}

public Param1CKEmbeddable(String id) {
    this.id = id;
}


@Override
public int hashCode() {
    return Objects.hash(parentId, id);
}

}

From the "Parent", the connection is straighforward:

@OneToMany(mappedBy="parent")
@Cascade(value = CascadeType.ALL)
private List<Param1CK> params3 = new LinkedList<Param1CK>();

Hope this helps the next person, who will struck into this issue.

Draaksward
  • 759
  • 7
  • 32