Нарушение ограничения внешнего ключа при сохранении класса многие-к-одному - PullRequest
1 голос
/ 11 апреля 2010

Я получаю сообщение об ошибке при попытке сохранить сущность «многие в один»:

Внутреннее исключение: org.postgresql.util.PSQLException: ОШИБКА: вставка или обновление таблицы «concept» нарушает ограничение внешнего ключа «concept_concept_class_fk» Подробно: Ключ (concept_class_id) = (Concept) отсутствует в таблице "concept_class". Код ошибки: 0 Вызов: INSERT INTO concept (concept_key, description, label, code, concept_class_id) VALUES (?,?,?,?,?) bind => [27, description_1, label_1, code_1, Concept] Запрос: 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;
    }

}
* +1009 * ...

Вот как определяются две сущности:

@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 для concept_class_id. Следует вставить слово LOINC_TEST . Я не могу понять, почему он использует это слово. Я использовал отладчик для просмотра Concept и экземпляра ConceptClass, и ни один из них не содержит этого слова. Я использую eclipselink. Кто-нибудь знает, почему это происходит?

1 Ответ

0 голосов
/ 23 апреля 2010

У вас есть два противоречивых определения для столбца concept_class_id.

Столбец concept_class_id появляется в аннотациях @DiscriminatorColumn и @JoinColumn вокруг класса Concept. Вы не можете сделать это. Эти две аннотации борются за контроль над столбцом concept_class_id в концепции таблицы. @DiscriminatorColumn побеждает. Вот почему имя класса «Concept» появляется в привязке SQL, где вы ожидаете идентификатор ConceptClass.

Кстати, @DiscriminatorColumn полезен только тогда, когда несколько классов совместно используют одну таблицу. @ D / C записывает, какой класс представляет строка. Если в таблице концептов хранятся только объекты класса Concept, вы можете удалить @DiscriminatorColumn. @ D / C не имеет смысла, если в таблице нет нескольких классов.

Подводя итог, исправления включают в себя:

  • Измените "имя" в аннотации @DiscriminatorColumn от Concept
  • Измените "имя" в аннотации @JoinColumn Concept.conceptClass
  • Удалить аннотацию @DiscriminatorColumn для класса Concept

НТН

...