【问题标题】:Foreign Key constraint violation when persisting a many-to-one class保持多对一类时违反外键约束
【发布时间】:2010-04-11 06:20:47
【问题描述】:

尝试持久化多对一实体时出现错误:

内部异常:org.postgresql.util.PSQLException:错误:在表“concept”上插入或更新违反了外键约束“concept_concept_class_fk” 详细信息:表“concept_class”中不存在键 (concept_class_id)=(Concept)。 错误代码:0 调用:INSERT INTO concept (concept_key, description, label, code, concept_class_id) VALUES (?, ?, ?, ?, ?) 绑定 => [27,描述_1,标签_1,代码_1,概念] 查询:InsertObjectQuery(com.mirth.results.entities.Concept[conceptKey=27]) 在 com.sun.ejb.containers.BaseContainer.checkExceptionClientTx(BaseContainer.java:3728) 在 com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3576) 在 com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1354) ... 101 更多

这是尝试持久化它的方法。我在该行的位置发表了评论:

@Override
public void loadConcept(String metaDataFilePath, String dataFilePath) throws Exception {
    try {
        ConceptClassMetaData conceptClassMetaData = (ConceptClassMetaData) ModelSerializer.getInstance().fromXML(FileUtils.readFileToString(new File(metaDataFilePath), "UTF8"));


        em.executeNativeQuery(conceptClassMetaData.getCreateStatement());

        ConceptClassRow conceptClassRow = conceptClassMetaData.getConceptClassRow();

        ConceptClass conceptClass = em.findByPrimaryKey(ConceptClass.class, conceptClassRow.getId()); 
        if (conceptClass == null) {
            conceptClass = new ConceptClass(conceptClassRow.getId());
        }
        conceptClass.setLabel(conceptClassRow.getLabel());
        conceptClass.setOid(conceptClassRow.getOid());
        conceptClass.setDescription(conceptClassRow.getDescription());

        conceptClass = em.merge(conceptClass);            

        DataParser dataParser = new DataParser(conceptClassMetaData, dataFilePath);
        for (ConceptModel conceptModel : dataParser.getConceptRows()) {
            ConceptFilter<Concept> filter = new ConceptFilter<Concept>(Concept.class);
            filter.setCode(conceptModel.getCode());
            filter.setConceptClass(conceptClass.getLabel());
            List<Concept> concepts = em.findAllByFilter(filter);

            Concept concept = new Concept();
            if (concepts != null && !concepts.isEmpty()) {
                concept = concepts.get(0);
            }
            concept.setCode(conceptModel.getCode());
            concept.setDescription(conceptModel.getDescription());
            concept.setLabel(conceptModel.getLabel());
            concept.setConceptClass(conceptClass);
            concept = em.merge(concept);  //THIS LINE CAUSES THE ERROR!

        }
    } catch (Exception e) {            
        e.printStackTrace();
        throw e;
    }

}

...

以下是这两个实体的定义方式:

@Entity
@Table(name = "concept")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="concept_class_id", discriminatorType=DiscriminatorType.STRING)
public class Concept extends KanaEntity {
    @Id
    @Basic(optional = false)
    @Column(name = "concept_key")
    protected Integer conceptKey;
    @Basic(optional = false)
    @Column(name = "code")
    private String code;
    @Basic(optional = false)
    @Column(name = "label")
    private String label;
    @Column(name = "description")
    private String description;
    @JoinColumn(name = "concept_class_id", referencedColumnName = "id")
    @ManyToOne
    private ConceptClass conceptClass;

...


@Entity
@Table(name = "concept_class")
public class ConceptClass extends KanaEntity {
    @Id
    @Basic(optional = false)
    @Column(name = "id")
    private String id;
    @Basic(optional = false)
    @Column(name = "label")
    private String label;
    @Column(name = "oid")
    private String oid;
    @Column(name = "description")
    private String description;
....

另外,重要的是正在生成的 sql:

INSERT INTO concept_class (id, oid, description, label) VALUES (?, ?, ?, ?) bind => [LOINC_TEST, 2.16.212.31.231.54, 这是一个元数据文件对于 LOINC_TEST,loinc_test]

INSERT INTO concept (concept_key, description, label, code, concept_class_id) VALUES (?, ?, ?, ?, ?) bind => [27, description_1, label_1, code_1, Concept]

失败的原因很明显:它为concept_class_id 插入了Concept 这个词。它应该插入单词 LOINC_TEST。我想不通它为什么用这个词。我使用调试器查看了 Concept 和 ConceptClass 实例,它们都没有包含这个词。我正在使用eclipselink。有谁知道为什么会这样?

【问题讨论】:

    标签: jpa ejb eclipselink


    【解决方案1】:

    对于列 concept_class_id,您有两个相互冲突的定义。

    concept_class_id 列出现在类Concept 周围的@DiscriminatorColumn 和@JoinColumn 注释中。你不能那样做。这两个注释正在争夺表概念中列concept_class_id 的控制权。 @DiscriminatorColumn 恰好赢了。这就是为什么类名“Concept”出现在您期望 ConceptClass id 的 SQL 绑定中。

    顺便说一句,@DiscriminatorColumn 只有在多个类共享一个表时才有用。 @D/C 记录一行代表哪个类。如果概念表中只存储了 Concept 类的对象,则可以删除 @DiscriminatorColumn。 @D/C 是没有意义的,除非你在一个表中有多个类。

    总而言之,修复包括:

    • 在 Concept 的 @DiscriminatorColumn 注释中更改“名称”
    • 在 Concept.conceptClass 的 @JoinColumn 注释中更改“名称”
    • 删除类 Concept 上的 @DiscriminatorColumn 注释

    HTH

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 2014-10-16
      • 2014-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多