我需要实现历史化,因为我们必须为任何更新的记录创建新记录。所有记录都有一个删除并插入的日期。因此,我们所做的是在更新时将已删除的日期设置为NOW,并插入插入日期为NOW并删除日期为NULL的新记录。使用JPA进行历史记录
我使用JPA和eclipseLink作为持久提供者。我的问题是,当JPA认为需要更新时,我需要执行“额外”插入操作。到目前为止,我已经在非元数据字段的实体上设置了updatable = false。我更新了插入日期和删除日期以及用户名。哪一个按预期工作。我现在需要做的就是制作额外的插页。
我想解决这个问题,使用entityListener,其中我实现@postUpdate和@preUpdate。如果我尝试提交我在@postUpdate上执行的新事务,那么我无法使其工作,因为我最终陷入僵局。如果我没有创建一个新的EntityManager和一个事务,而仅仅是在现有的EntityManager上持续存在调用,出于某种原因,“新”实体不会发生任何事情。下面
代码:
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");
}
}
插入和删除日期是多余的,如果由于某种原因删除日期与下一个插入日期之间存在间隙,可能会导致您遇到麻烦。特别是如果你在你的例子中设置日期,因为不同的方法可能会在'Calendar.getInstance()'返回一个接一个的值时执行。 – SpaceTrucker 2015-03-03 08:18:16
相关:http://stackoverflow.com/questions/9542366/how-to-implement-a-temporal-table-using-jpa – SpaceTrucker 2015-03-03 08:22:39
显然,在完成的例子中,我将日历设置为本地对象,并将其用于两者声明。我很好奇,但是如何指示删除的行没有删除日期? – Michael 2015-03-03 12:59:26