用审计字段+历史表实现可追溯:主表加created_by/created_time/updated_by/updated_time四字段,历史表存操作类型、前后JSON数据、操作人及时机;Service层统一拦截记录,查询时对比差异返回变更字段。

核心思路:用审计字段 + 历史表实现可追溯
不依赖第三方框架也能做好修改记录,关键是把“谁、什么时候、改了什么”这三个信息存下来。最稳妥的方式是业务表加审计字段 + 单独建历史表,既不影响主表查询性能,又能完整还原每次变更。
主表加基础审计字段
在需要追踪的业务表(比如 user_info)里加四列:
- created_by:创建人ID(如用户ID或系统标识)
-
created_time:创建时间(建议用
datetime(3)或timestamp,支持毫秒) - updated_by:最后修改人ID
- updated_time:最后修改时间
这些字段用于快速定位最新状态和责任人,但不记录每次修改的快照——那是历史表的事。
设计独立的历史表(关键)
为每个需审计的主表建一张对应的历史表,例如 user_info_history,结构包含:
立即学习“Java免费学习笔记(深入)”;
- id:自增主键或 UUID
- main_id:关联主表的 ID(如 user_id)
-
operation_type:枚举值,如
INSERT/UPDATE/DELETE - before_data:JSON 字段,存修改前的完整对象(仅 UPDATE/DELETE 时有值)
- after_data:JSON 字段,存修改后的完整对象(仅 INSERT/UPDATE 时有值)
- operator_id:操作人 ID
- operate_time:操作时间(精确到毫秒)
- remark:可选,补充说明(如“批量导入”、“后台人工修正”)
用 JSON 存前后数据,灵活兼容字段变更;不用每字段拆成列,避免历史表随主表频繁 DDL。
模板采用响应式设计,自动适应手机,电脑及平板显示;满足单一店铺外卖需求。功能:1.菜单分类管理2.菜品管理:菜品增加,删除,修改3.订单管理4.友情链接管理5.数据库备份6.文章模块:如:促销活动,帮助中心7.单页模块:如:企业信息,关于我们更强大的功能在开发中……安装方法:上传到网站根目录,运行http://www.***.com/install 自动
在 Service 层统一拦截修改逻辑
不要在每个 DAO 或 Controller 里手写 insert history,而是封装一个通用方法。例如:
- 更新用户前,先查出旧数据
User old = userMapper.selectById(id) - 执行更新
userMapper.updateById(user) - 构造历史记录:
saveHistory(id, "UPDATE", old.toJson(), user.toJson(), userId, now)
删除和新增同理。可以抽成 AuditService,配合 Spring AOP 或模板方法进一步解耦,但起步阶段手动调用已足够清晰可控。
查询历史时注意实用细节
前端常要“看某条记录的所有修改轨迹”,后端接口返回示例结构:
[{"version": 1, "time": "2024-05-01 10:22:33.123", "by": "admin", "change": {"name": ["张三", "张小三"], "email": ["old@x.com", "new@x.com"]}}, ...]实际组装时,从 history 表按 main_id + operate_time 排序查出所有记录,再用 JSON 工具(如 Jackson)对比 before_data 和 after_data 的差异字段,只返回真正变化的 key-value 对,避免传输冗余数据。
基本上就这些。不复杂但容易忽略的是:历史表要定期归档(比如按月分区),以及 JSON 字段记得建好索引(MySQL 8.0+ 支持 JSON 列路径索引),不然查得慢。









