使用JPA进行历史化

时间:2015-03-03 07:45:25

标签: java oracle jpa eclipselink

我需要实现Historization,因为我们必须拥有任何更新记录的新记录。所有记录都有删除和插入的日期。因此,我们所做的是在更新时将删除的日期设置为NOW,并插入插入日期为NOW且删除日期为NULL的新记录。

我使用JPA和eclipseLink作为持久性提供程序。我的问题是,当JPA认为需要更新时,我需要执行“额外”插入。到目前为止,我已在Entity上为非元数据字段设置了updatable = false。我更新了insertDate和deletionDate以及userName。哪一切都按预期工作。我现在需要做的就是制作额外的插页。

我正在尝试使用entityListener来解决这个问题,我实现了@postUpdate和@preUpdate。我无法让它工作,因为如果我尝试提交我在@postUpdate上执行的新事务,我最终陷入僵局。如果我不创建一个新的EntityManager和一个事务,但仅仅在现有的EntityManager上调用持久化由于某种原因,“new”实体没有任何反应。

以下代码:

import java.util.Calendar;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PostPersist;
import javax.persistence.PostUpdate;
import javax.persistence.PreUpdate;

public class ColorEntityListener {

    public ColorEntityListener()
    {       
    }

    @PreUpdate 
    void onPreUpdate(ColorEntity c) 
    {
        System.out.println("onPreUpdate");
        c.setDeletionDate(Calendar.getInstance());      
    }

    @PostUpdate 
    void onPostUpdate(ColorEntity c) 
    {   
        System.out.println("onPostUpdate");
        createNewRecord(c);
    }

    @PostPersist
    void onPostPersist(ColorEntity c) 
    {   
        System.out.println("onPostPersist");
    }

    private void createNewRecord(ColorEntity c) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("v2_tl");
        EntityManager em = factory.createEntityManager();

        em.getTransaction().begin();

        ColorEntity cNew = new ColorEntity();
        cNew.setPrNumber(c.getPrNumber());
        cNew.setHs(c.getHs());
        cNew.setCountryCode(c.getCountryCode());
        cNew.setValidFrom(c.getValidFrom());
        cNew.setValidUntil(c.getValidUntil());
        cNew.setColorCode(c.getColorCode());

        //cNew.setId(0);
        cNew.setInsertDate(Calendar.getInstance());
        cNew.setDeletionDate(null);

        em.persist(cNew);

        System.out.println("Before commit of new record");
        em.getTransaction().commit();
        System.out.println("After commit of new record");
    }
}

2 个答案:

答案 0 :(得分:2)

Eclipselink通过添加@Customizer内置了对历史记录的支持。 有关如何使用它的示例,请参阅此链接:

http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

答案 1 :(得分:1)

请看hibernate envers project。它解决了逆转任务 - 保存有关变更审计的信息。但它可以存储适合您的任务格式的信息。