繁体   English   中英

弹簧靴。 复合键和级联

[英]Spring boot. Composite key and cascades

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

我有一个父实体(在底部堆栈跟踪中称为 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 无法解析密钥,并执行一个循环来解析父密钥,即解析为 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 类设为 Embeddable,因为您将多对一关系作为 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)改变Parent实体上的mappedBy以考虑嵌入关系:

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

如果有人偶然发现了这个问题(或者直到提出更好的解决方案),这就是对我真正有用的方法(我为令人眼花缭乱的类和元素命名道歉,过去几天一直在尝试这个)。 取自@OneToMany 和复合主键?

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

这是可嵌入的定义:

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

公共 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);
}

}

从“父”,连接是直截了当的:

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

希望这能帮助下一个人,他将解决这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM