在Spring MVC / Spring Data项目中,我需要实现一种机制来跟踪历史记录,呈现差异并将更改还原为实体对象。
假设我有一个与其他人建立关系的实体:
@Entity
public Class ModelA{
@OneToOne(cascade = CascadeType.ALL)
private ModelB modelB;
@OneToOne(cascade = CascadeType.ALL)
private ModelC modelC;
}
我希望获得更改列表,比较和还原它们的能力。我知道使用Ruby有提供这种功能的库,但我不知道Java中是否存在这样的东西。
Spring有historiography API并且Hibernate Envers已经被整合到Core功能中,尽管我仍然找不到一个简单的例子或一些如何实现它的指导。
如果它是相关的,使用的数据库是PostgreSQL和Oracle 11g,但我想保持数据库独立。
答案 0 :(得分:2)
请使用Enver和Auditions。
答案 1 :(得分:1)
在this article中,Christian Bauer(Hibernate提交者和Hibernate in Action和Java Persistence with Hibernate的作者)给出了一个非常有趣的方法。
您创建一个HISTORY表:
create table ITEM (
ITEM_ID NUMBER(19) NOT NULL,
DESC VARCHAR(255) NOT NULL,
PRICE NUMBER(19,2) NOT NULL,
PRIMARY KEY(ITEM_ID)
)
create table ITEM_HISTORY (
ITEM_ID NUMBER(19) NOT NULL,
DESC VARCHAR(255) NOT NULL,
PRICE NUMBER(19,2) NOT NULL,
VERSION NUMBER(10) NOT NULL,
PRIMARY KEY(ITEM_ID, VERSION)
)
然后将实体映射到视图:
create or replace view ITEM_VERSIONED (ITEM_ID, VERSION, DESC, PRICE) as
select I.ITEM_ID as ITEM_ID,
(select max(IH.VERSION)
from ITEM_HISTORY HI
where HI.ITEM_ID = I.ITEM_ID) as VERSION,
I.DESC as DESC,
I.PRICE as PRICE
from ITEM I
并且由PostgreSQL和Oracle支持的INSTEAD OF TRIGGERS解决了DML语句:
create or replace trigger ITEM_INSERT
instead of insert on ITEM_VERSIONED begin
insert into ITEM(ITEM_ID, DESC, PRICE)
values (:n.ITEM_ID, :n.DESC, :n.PRICE);
insert into ITEM_HISTORY(ITEM_ID, DESC, PRICE, VERSION)
values (:n.ITEM_ID, :n.DESC, :n.PRICE, :n.VERSION);
end;
create or replace trigger ITEM_UPDATE
instead of update on ITEM_VERSIONED begin
update ITEM set
DESC = :n.DESC,
PRICE = :n.PRICE,
where
ITEM_ID = :n.ITEM_ID;
insert into ITEM_HISTORY(ITEM_ID, DESC, PRICE, VERSION)
values (:n.ITEM_ID, :n.DESC, :n.PRICE, :n.VERSION);
end;
即使对于可能不使用Hibernate的其他应用程序,它也可以工作,但它们在同一个DB上运行。
答案 2 :(得分:0)
如果我理解得很清楚,你要问的是某种Memento pattern来管理一些受历史追踪影响的实体。
在这种情况下,我的建议是将Spring Data配置为支持第二个数据库(即跟踪数据库),您将在其中插入您感兴趣的实体的历史记录。 然后,您可以创建一个新的注释(可能使用AspectJ)并将其应用于您的DAO(例如,如果您正在使用它们,则应用于您的存储库)。这样,每次在跟踪类上(或者更确切地说,在管理要跟踪的类的dao / repository上)进行CRUD操作时,都会在跟踪数据库中进行“插入”,以便存储只有发生。
我可以给你this reference,这与你的需求不完全相符,但可以帮助你找到解决问题的解决方案。