Мне нужно реализовать Historization в том смысле, что у нас должна быть новая запись для любой обновленной записи. Все записи имеют удаленную и вставленную дату. Итак, мы делаем, чтобы дата удаления была обновлена до версии NOW при вставке новой записи с датой вставки NOW и удаленной датой NULL.
Я использую JPA с eclipseLink как постоянный провайдер. Моя проблема в том, что мне нужно сделать "лишнюю" вставку, когда JPA подумает, что ей нужно обновить. До сих пор я установил updatable = false в Entity для полей не метаданных. Я обновляю insertionDate и deleteionDate и имя пользователя. Что все работает так, как ожидалось. Все, что мне теперь нужно сделать, это сделать дополнительную вставку.
Я пытаюсь решить проблему, используя 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");
}
}
Eclipselink построил поддержку Истории, добавив @Customizer
. См. Эту ссылку для примера о том, как ее использовать:
Пожалуйста, посмотрите проект hibernate envers. Он решает задачу восстановления - держите информацию об изменении аудита. Но он сохраняет информацию в хорошем состоянии для вашего формата задачи.
Calendar.getInstance()
возвращает значения, которые следуют один за другим.