【问题标题】:JPA: How to update grandchild entities when updating grandfather entity?JPA:更新祖父实体时如何更新孙子实体?
【发布时间】:2016-11-16 16:01:47
【问题描述】:

我创建了表格来存储来自解析非常嵌套的 xml 文件的信息。因此,我的数据库中的表也是嵌套的。顶级实体称为 SpecimentTb。

@Entity
@Table(name="SPECIMEN_TB")
public class SpecimenTb implements Serializable {
    private String mrn;
    @Column(name="SPECIMEN_NO", unique = true)
    private String specimenNo;
    @OneToMany(mappedBy="specimenTb", cascade=CascadeType.ALL)
    private List<FmReportTb> fmReportTbs;
}

SpecimenTb 有一个名为 FmReportTb 的子实体,它与 FmReportGeneTb 有自己的单对多关系

@Entity
@Table(name="FM_REPORT_TB")
public class FmReportTb implements Serializable {
    //bi-directional many-to-one association to SpecimenTb
    @ManyToOne
    @JoinColumn(name="SPECIMEN_ID")
    private SpecimenTb specimenTb;
    @OneToMany(mappedBy="fmReportTb", cascade=CascadeType.ALL)
    private List<FmReportGeneTb> fmReportGeneTbs;
}

稍后可能会有更新版本的文件,所以我需要在我的代码中实现更新方案。当我坚持的时候,我会在 SpecimentTb 中通过标本号查找记录。如果不存在,则插入新记录。否则,更新相同的记录、父亲、孩子和孙子孙女。

    SpecimenDao specimenDao = new SpecimenDao(em);
    SpecimenTb specimenTb = specimenDao.findSpecimenBySpecno(blockId);
    FmReportTb report = null;
    if (specimenTb != null) { // update
        report = specimenTb.getFmReportTbs().get(0);
    } else { // insert
        report = new FmReportTb();
    }
    if (report.getFmReportGeneTbs() != null) { // update
        geneList = report.getFmReportGeneTbs();
        geneList.clear();
    } else { //insert
        geneList = new ArrayList<FmReportGeneTb>();
    }
    // parse "Genes" section of xml and store in geneList
    for (Node gene : genes) {
        FmReportGeneTb geneTb = new FmReportGeneTb();
        << set a bunch of stuff for geneTb>>
        geneTb.setFmReportTb(report);
    }
    geneList.add(geneTb);
    report.setFmReportGeneTb(geneList);
    if (specimenTb == null) { // insert new record
        specimenTb = new SpecimenTb();
        specimenTb.setSpecimenNo(blockId);
        specimenTb.setMrn(mrn);
        report.setSpecimenTb(specimenTb);
        reports.add(report);
        specimenTb.setFmReportTbs(reports);
        specimenDao.persistSpecimen(specimenTb);
    } else { // update
        report.setSpecimenTb(specimenTb);
        reports.add(report);
        specimenDao.updateSpecimen(specimenTb, mrn, reports);
    }

在DAO类中,persist和update方法如下: //插入

public void persistSpecimen(SpecimenTb specimen) {
    EntityTransaction transaction = entityManager.getTransaction();
    try {
        transaction.begin();
        entityManager.persist(specimen);
        transaction.commit();
    } catch (Exception e) {
        transaction.rollback();
    }
}

//更新

public void updateSpecimen(SpecimenTb specimen, String mrn, List<FmReportTb> reports) {
    EntityTransaction transaction = entityManager.getTransaction(); 
    try {
        transaction.begin();
        specimen.setSpecimenNo(blockId);
        specimen.setMrn(mrn);
        specimen.setFmReportTbs(reports);
        transaction.commit();
    } catch (Exception e) {
        transaction.rollback();
    }
}

插入完全符合我的要求,感谢cascade=CascadeType.ALL,它保留了父实体和下面的所有实体。但是,当我更新时,它确实会更新 SpecimenTb 和 FmReportTb 中的旧记录,但往往会在 FmReportGeneTb 中插入一系列新记录。所以我最终在 FmReportGeneTb 中附加了一组新记录,这些记录链接到同一个 FmReportTb 而不是更新(新旧版本中的 GeneList 长度可能不同)。实际上有我没有显示的 FmReportGeneTb 的子实体和孙实体。如何从上到下更新所有相关表?

【问题讨论】:

    标签: java jpa sql-update entity persistence


    【解决方案1】:

    我不知道你在FmReportTb上设置了哪些其他字段,但是看到你的代码,第一行有一个

    FmReportTb report = new FmReportTb();

    这解释了为什么您的样本中最终有两条 FmReportTb 记录。 如果你想更新现有的FmReportTb,你应该在更新之前设置它的id。

    【讨论】:

    • 我编辑了我的帖子,我修改了设置 FmReportTb 的方法。现在它正在更新 FmReportTb 而不是插入。但是有一个名为 FmReportGeneTb 的 FmReportTb 子实体我也需要更新。由于它是一个列表,它并不是真正在genetb 级别更新,而是删除旧的记录列表并插入新的记录。我该怎么做?
    • 如果您使用的是休眠,请尝试在 fmReportGeneTbs 上添加一个额外的@Cascade({DELETE_ORPHAN})(此级联来自休眠)。
    • 我正在使用 JPA 2.1。我应该改用orphanRemoval=true 吗?
    • 因为我要删除整个geneTb 列表,我可以只clear() 列表而不是迭代列表,删除它们中的每一个并取消父级吗?
    • 在 fmReportGeneTbs 列表中使用 'orphanRemoval=true' 您可以清除列表并添加新列表。您不需要取消每个父母。
    猜你喜欢
    • 2015-11-22
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2015-01-26
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多