春天的靴子。复合键和级联

问题描述 投票:1回答:2

有人可以解释,这应该如何实现?

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

class Parent {
   @Id
   private int id;
}

我有一个Child(堆栈跟踪中的Param1CK,params3表),其ID为Composite,依赖于“Parent”和“行号”:

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

父母中的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)
java hibernate spring-boot jpa composite-primary-key
2个回答
1
投票

1)让你成为id类Embeddable,因为你有一个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 = ...;

0
投票

如果有人偶然发现(或者直到会有更好的解决方案),这里实际上对我有用(我为眼睛燃烧类和元素命名道歉,过去几天一直试着这个)。取自@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;
    }
}

这是可嵌入的定义:

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

}

从“父”,连接很简单:

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

希望这有助于下一个将触及这个问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.