问题描述
用Spring来开发一个WEb系统。比如:现在实体 Problem,Problem有一下属性:Cateory,Title,description。需求是可以更新Problem的数据库记录,但是,用户可以在页面上看到这个Problem的历史记录,需要看到具体被修改属性的原始值跟新的值。没有好的设计思路。求解。。。
解决方案
看到这个需求,我第一反应是设计在java层做更新记录好像更方便。不需要任何其他知识点了。数据库加一张表就行,比如名叫record表里面 entry property old new date 类似这么几个字段,java层再加一个这个表对应的实体类Record,并且有一个insert方法在Problem的update方法里,很容易能获取到这几个值,update成功以后创建一个Record对象insert到表里。 这样做的好处是可以收集任意一个实体类的修改记录,可能有User,Person等等。查询的时候根据entry name这个字段来区分。这样无论多少次修改,都能保存直观的历史记录。至于这样污染了update的代码,你可以思考下依靠spring的aop编程,比如后置通知之类的,将比较新老值,组装成Record对象等逻辑,分离到一个通用、独立的方法里。其实这一点还是需要思考一下,如果才能更优雅地实现。
解决方案二:
两种方式,一种是简历一张和原表一样的表,对每个可能修改的字段列增加一个修改值的列,再增加一个字段是版本号,这样可以随意调取任何一个版本的记录,速度快,缺点是不可复用,只能针对某一个表,如果你的原表是主子表,那你新增的表就要和原表的结构一样,比较比如原表是合同表,有合同项子表,有订单子表,你都要一一复制。第二种是使用修改表,建一张修改记录主表,记录修改时间,修改人,审核人等主信息,配一张修改项子表,记录修改的表名或者对象名,对象主键id,修改的对象的属性名,原值,修改值,如果是子对象,可以在对象名和对象id上拼接。这种方式适用比较多的情况,具有通用性,但是调取任何一个版本,你需要一个复原引擎,读取你指定版本之后每一个版本,进过处理才能还原到指定版本。两种方式的选择需要自己判断一下需求,选择适合自己的方式,至于到底是触发器控制,还是对修改逻辑进行监控就没那么重要了。
解决方案三:
如果是新建一个历史表,每次复制,这样能查询出历史版本,但是如果要知道修改的字段,还需要 取出数据对比才知道,如果新建的表是记录 old值与new值的这种表,那么就很方便查看修改前的值与修改后的值,但这种方式不能查看历史某一版本的全部数据,根据需求把握,我以前是用的第二种方案,记录 用户修改属性,然后让管理员审核,可以只通过部分字段或者驳回部分字段。
解决方案四:
可以创建一个与原表结构相同的历史表,可以比原表多一些数据操作的标记字段,然后对原表添加Trigger,在原表进行Update,Insert,Delete操作的时候向历史表添加数据(可以考虑同时添加Before Image和After Image).Trigger可以做得更简单一些。假设原表的表名是TBL_AAA,有若干列A1,A2...,那么Audit表就可以为AUD_AAA,设有A1,A2...,AUDIT_DT,AUDIT_MODE,AUD_IMG_TYPE; CREATE OR REPLACE TRIGGER TRI_AAA AFTER INSERT OR UPDATE ON TBL_AAA REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW DECLARE auditMode VARCHAR2 (6); curr_date date; BEGIN IF UPDATING THEN auditMode := 'update'; ELSIF INSERTING THEN auditMode := 'insert'; END IF; curr_date:=sysdate; IF UPDATING THEN insert into AUD_AAA ( A1, A2, ., ., ., AUDIT_MODE, AUD_IMG_TYPE, AUDIT_DT ) values ( :OLD.A1, :OLD.A2, :OLD.., :OLD.., :OLD.., auditMode, 'before', curr_date ); END IF; IF INSERTING or UPDATING THEN insert into AUD_AAA ( A1, A2, ., ., ., AUDIT_MODE, AUDIT_IMG_TYPE, AUDIT_DT ) values ( :NEW.A1, :NEW.A2, :NEW.., :NEW.., :NEW.., .auditMode, 'after', curr_date ); END IF; EXCEPTION WHEN OTHERS THEN RAISE; END;
解决方案五:
1、版本号每修改一下 复制一条记录 并版本号+12、历史表可以通过如下完成复制:1、触发器2、应用程序内
解决方案六:
可以考虑分表,一个历史表一个原始表,每次更新的时候将原始数据存到历史表中,然后在更新原始表