Историзация с JPA

1

Мне нужно реализовать 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");
    }
}
  • 0
    добавленная и удаленная дата является излишней и может привести к неприятностям, если по какой-либо причине существует разрыв между удаленной и следующей вставленной датой. Особенно если вы установите даты, как в вашем примере, потому что разные методы могут выполняться в моменты, когда Calendar.getInstance() возвращает значения, которые следуют один за другим.
  • 0
    связанные: stackoverflow.com/questions/9542366/…
Показать ещё 2 комментария
Теги:
jpa
eclipselink

2 ответа

2

Eclipselink построил поддержку Истории, добавив @Customizer. См. Эту ссылку для примера о том, как ее использовать:

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

  • 0
    Насколько я вижу, это решает проблему, только если вы хотите хранить данные в отдельной таблице истории. Мы хотим сохранить данные в той же таблице, что и объект.
1

Пожалуйста, посмотрите проект hibernate envers. Он решает задачу восстановления - держите информацию об изменении аудита. Но он сохраняет информацию в хорошем состоянии для вашего формата задачи.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню