RCP 编辑器和 JPA 合并

RCP Editor and JPA merge

我正在更新基于 RCP 的应用程序以使用来自 Hibernate 3.x 的 JPA 2.1(EclipseLink 的实现)。 JPA 合并行为给我带来了问题。我看到的问题是,当我将返回值分配给 RCP 编辑器(继承自 FormEditor)中的模型对象时,它是一个新实体,并且更改不会在后续保存中保留。

我正在寻求有关如何使用从 JPA.merge() 返回的新对象以最佳方式更新 RCP 编辑器模型的意见。

注意:我了解hibernate 的saveOrUpdate 和JPA 的persist 之间的区别。

我看到的两种方法是:

  1. 在我的服务层中,将 JPA.merge() 返回的新实体深复制到传递给 service.save() 方法的实体中,并且不要在editor.doSave() 方法。
  2. 将 RCP 编辑器中的模型关联到从 JPA.merge()
  3. 返回的新实体

对象图相当复杂和深入,因此编写深层副本并非易事。但是,我不知道如何处理上面的#2。

我愿意接受任何关于如何处理#1/#2 的想法,或者是否有我遗漏的选项#3 - #n。

感谢您花时间阅读我的问题!

这是我目前的Editor.doSave方法

@Override
public void doSave(IProgressMonitor monitor) {
    this.overviewPage.getDataBindingContext().updateModels();
    this.getActivePageInstance().getManagedForm().commit(true);
    try {
        motor = Activator.getAcMotorEntity().save(motor);
    } catch (BusinessException e) {
        StatusManager.getManager().handle(
                new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to save the motor to the database", e),
                StatusManager.LOG | StatusManager.SHOW);
    }
    if (motor.getId() == 1L) {
        this.setPartName("[DEFAULT VALUES]");
    } else {
        this.setPartName(this.motor.getJobNumber());
    }
    this.setDirty(false);
}

和我的 service.save() 调用 JPA 的合并

@Override
public IT save(IT entity) throws BusinessException {
    EntityManager em = factory.createEntityManager();
    IT savedEntity = null;

    getLogger().debug("Save {} with id of {} ", entity.getClass().getName(), ((IDatabaseEntity) entity).getId());
    try {
        em.getTransaction().begin();
        savedEntity = em.merge(entity); // re-attach
        em.getTransaction().commit();
        this.firePropertyChange(entity, savedEntity);
    } catch (OptimisticLockException ole) {
        getLogger().error("Load " + entity.getClass().getName() + " with id of " + ((IDatabaseEntity) entity).getId(), ole);
        throw JpaExceptionFactory.createRecordChanged(ole, entity == null ? 0 : ((IDatabaseEntity) entity).getId(),
                entity == null ? "null entity" : entity.getClass().getName());
    } catch (PersistenceException pe) {
        getLogger().error("Load " + entity.getClass().getName() + " with id of " + ((IDatabaseEntity) entity).getId(), pe);
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        throw JpaExceptionFactory.createPersistence(pe, entity == null ? 0 : ((IDatabaseEntity) entity).getId(),
                entity == null ? "null entity" : entity.getClass().getName());
    } catch (Throwable t) {
        getLogger().error("Load " + entity.getClass().getName() + " with id of " + ((IDatabaseEntity) entity).getId(), t);
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        throw JpaExceptionFactory.createUnknownDatabase(t, entity == null ? 0 : ((IDatabaseEntity) entity).getId(),
                entity == null ? "null entity" : entity.getClass().getName());
    } finally {
        if (em != null && em.isOpen()) {
            em.close();
        }
    }

问题原来是将编辑器字段映射到模型的数据绑定上下文仅在创建表单时才构建。该绑定继续指向原始实体。

解决方案是在调用 motor = Activator.getAcMotorEntity().save(motor); 后重建数据绑定上下文。这更新了绑定以指向从 JPA.merge() 返回的实体。