Java JPA(Hibernate)问题保存多通关系

Java JPA(Hibernate)问题保存多通关系,java,hibernate,jpa,Java,Hibernate,Jpa,我遇到了一个问题:我有一个实体定义,它与DefinitionInfo实体有一个OneToMany关系,当我尝试加载一个现有定义时,将DefinitionInfo添加到它的信息列表集合中,Saved说它找不到我刚刚添加到定义中的DefinitionInfo的实体。对此,我说‘呸!’我正在尝试向定义中添加一个新的定义信息,因此您当然不会找到它 代码如下: @Entity(name = "CohortDefinition") @Table(name="cohort_definition") @Name

我遇到了一个问题:我有一个实体定义,它与DefinitionInfo实体有一个OneToMany关系,当我尝试加载一个现有定义时,将DefinitionInfo添加到它的信息列表集合中,Saved说它找不到我刚刚添加到定义中的DefinitionInfo的实体。对此,我说‘呸!’我正在尝试向定义中添加一个新的定义信息,因此您当然不会找到它

代码如下:

@Entity(name = "CohortDefinition")
@Table(name="cohort_definition")
@NamedEntityGraph(
    name = "CohortDefinition.withDetail",
    attributeNodes = { @NamedAttributeNode(value = "details", subgraph = "detailsGraph") },
    subgraphs = {@NamedSubgraph(name = "detailsGraph", type = CohortDefinitionDetails.class, attributeNodes = { @NamedAttributeNode(value="expression")})}
)
public class CohortDefinition implements Serializable{

  private static final long serialVersionUID = 1L;
...
 @OneToMany(mappedBy="cohortDefinition", fetch= FetchType.LAZY)
  private Set<CohortGenerationInfo> generationInfoList;
...
+ Getters and Setters
这里是EmbeddedID类(信息的Id由定义的Id+表示不同类型信息的另一个实体的Id组成

@Embeddable
public class CohortGenerationInfoPK implements Serializable {

  private static final long serialVersionUID = 1L;

  public CohortGenerationInfoPK() {
  }

  public CohortGenerationInfoPK(Integer cohortDefinitionId, Integer sourceId) {
    this.cohortDefinitionId = cohortDefinitionId;
    this.sourceId = sourceId;
  }

  @Column(name = "id")
  private Integer cohortDefinitionId;

  @Column(name = "source_id")
  private Integer sourceId;

+ getter/setter
这就是我正在做的。这应该很简单,但我不明白发生了什么:

  Source source = this.getSourceRepository().findBySourceKey(sourceKey);
  CohortDefinition currentDefinition = this.cohortDefinitionRepository.findOne(id);
  CohortGenerationInfo info = findBySourceId(currentDefinition.getGenerationInfoList(), source.getSourceId());
  if (info == null)
  {
    info = new CohortGenerationInfo(currentDefinition.getId(), source.getSourceId());
    currentDefinition.getGenerationInfoList().add(info);
  }
  info.setStatus(GenerationStatus.PENDING)
    .setStartTime(Calendar.getInstance().getTime());

  this.cohortDefinitionRepository.save(currentDefinition);
下面是Hibernate选择,就在它爆炸之前:

Hibernate: select cohortgene0_.id as id1_4_0_, cohortgene0_.source_id as source_i2_4_0_, cohortgene0_.execution_duration as executio3_4_0_, cohortgene0_.is_valid as is_valid4_4_0_, cohortgene0_.start_time as start_ti5_4_0_, cohortgene0_.status as status6_4_0_, cohortdefi1_.id as id1_2_1_, cohortdefi1_.created_by as created_2_2_1_, cohortdefi1_.created_date as created_3_2_1_, cohortdefi1_.description as descript4_2_1_, cohortdefi1_.expression_type as expressi5_2_1_, cohortdefi1_.modified_by as modified6_2_1_, cohortdefi1_.modified_date as modified7_2_1_, cohortdefi1_.name as name8_2_1_ from cohort_generation_info cohortgene0_ inner join cohort_definition cohortdefi1_ on cohortgene0_.id=cohortdefi1_.id where cohortgene0_.id=? and cohortgene0_.source_id=?
以下是堆栈跟踪:

javax.persistence.EntityNotFoundException: Unable to find org.ohdsi.webapi.cohortdefinition.CohortGenerationInfo with id org.ohdsi.webapi.cohortdefinition.CohortGenerationInfoPK@3
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:183)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275)
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716)
    at org.hibernate.type.EntityType.resolve(EntityType.java:502)
    at org.hibernate.type.EntityType.replace(EntityType.java:366)
    at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:549)
    at org.hibernate.type.CollectionType.replace(CollectionType.java:690)
    at org.hibernate.type.TypeHelper.replace(TypeHelper.java:177)
    at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:407)
    at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:219)
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:192)
    at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
    at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:876)
    at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:858)
    at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:863)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1196)
我停在堆栈跟踪的合并部分。它似乎是从DB和mereg中获取现有实体。定义确实存在,只是添加了一个新的定义信息


有人有什么想法吗?我对如何构造数据库有一些限制,但我希望这不是一个数据库结构问题,而只是JPA的一些恼人的问题。

代码中有几个明显的问题

  • 由于您希望执行可传递持久性,即保存CohortDefinition也应保存CohortGenerationInfo,因此需要在OneToMany注释上设置cascade属性。例如
  • 您已经在coortDefinition和coortGenerationInfo之间设置了双向关系。作为最佳实践,最好显式设置关系两侧的值,而不是依赖ORM来完成。因此代码应该执行以下操作(最好将其放在帮助器方法中)

  • 哇,你太棒了。一定是cascade=CascadeType.All。我没有info.setcoortdefinition,因为coortdefinitioninfo()将拥有它的队列定义和另一个存储库中查找值的PK的附加整数值带到其构造函数中。我没有为这个其他整数值建立关系,因为它不重要,但是coortDefinition.ID和这个其他实体ID都构成coortDefinitionInfo的PKntity(因此是复合键)。再次感谢您!
    javax.persistence.EntityNotFoundException: Unable to find org.ohdsi.webapi.cohortdefinition.CohortGenerationInfo with id org.ohdsi.webapi.cohortdefinition.CohortGenerationInfoPK@3
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:183)
        at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
        at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275)
        at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
        at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
        at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989)
        at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716)
        at org.hibernate.type.EntityType.resolve(EntityType.java:502)
        at org.hibernate.type.EntityType.replace(EntityType.java:366)
        at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:549)
        at org.hibernate.type.CollectionType.replace(CollectionType.java:690)
        at org.hibernate.type.TypeHelper.replace(TypeHelper.java:177)
        at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:407)
        at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:219)
        at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:192)
        at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
        at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:876)
        at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:858)
        at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:863)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1196)
    
    @OneToMany(mappedBy="cohortDefinition", fetch= FetchType.LAZY, cascade= CascadeType.ALL)
    
    currentDefinition.getGenerationInfoList().add(info);
    info.setCohortDefinition(currentDefinition);