java - Spring Boot 。复合键和级联

标签 java hibernate spring-boot jpa composite-primary-key

有人可以解释一下,这实际上应该如何实现吗?

我有一个父实体(在底部堆栈跟踪中称为 Executor):

class Parent {
   @Id
   private int id;
}

我有一个子项(堆栈跟踪中的 Param1CK,params3 表),其 Id 是复合的,并且依赖于“父项”和“行号”:

@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() {...}
}

parent中Child的集合描述为:

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

这一点似乎没有得到正确的解决。

当我尝试做:

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

并且执行多次“保存”操作,Hibernate无法解析 key ,并执行一个循环来解析父 key ,即解析为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)

这会持续很长的循环,直到出现 StackOverflow 异常。最后指出:

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)

最佳答案

1) 让你的 id 类可嵌入,因为你有一个 ManyToOne 关系作为 id 的一部分:

@Embeddable
class ChildID implements Serializable{

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

2) 更改 Child 类:

@Entity
class Child {

   @EmbeddedId
   private ChildID id;

3) 更改父实体上的 mappedBy 以考虑嵌入关系:

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

关于java - Spring Boot 。复合键和级联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55758647/

相关文章:

java - 如何通过语言环境设置双重格式

java - Spring-Boot 无法启动嵌入式 Tomcat

java - Spring安全配置requestMatchers.hasRole()总是给出403禁止状态

java - 我的碰撞是 buggy ,有时会剧烈振动或出界

java - OPENGL Android获取我的图像的坐标

java - Hibernate_sequence 表生成

java - 在 JSP 上使用 Hibernate

java - 如何在不将 List 包装在其他类中的情况下验证 spring Controller 参数中 List 中的每个对象?

java - 安装spring boot后的Intellij "cannot resolve symbol"

java - 多线程和并发上下文中的 HttpClient 行为