操作记录精细到字段级别,有比较干净的方案么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
taloricag
V2EX    程序员

操作记录精细到字段级别,有比较干净的方案么?

  •  
      taloricag 2021-11-27 02:19:44 +08:00 3266 次点击
    这是一个创建于 1415 天前的主题,其中的信息可能已经有所发展或是发生改变。
    就是 post 请求,需要知道修改到数据库改了什么字段做操作记录
    实际上现在操作记录的实现已经是 AOP ,在路由层丢给一个单独的控制层去解决操作记录的问题
    但是在路由层不可能记录到字段级别,毕竟也不可能在这个地方去查数据
    所以有没啥干净一点的方案,实在是不想在业务逻辑的 controller 里再去逐个字段做对比...

    或许最理想的方案是在 ORM 去做,但是目前对 ORM 的控制力实在有点弱...(go / gorm
    16 条回复    2025-06-25 21:28:46 +08:00
    wd
        1
    wd  
       2021-11-27 06:45:02 +08:00 via iPhone
    数据库 trigger
    MIUIOS
        2
    MIUIOS  
       2021-11-27 08:01:12 +08:00 via iPhone   1
    我的做法是 binlog ,用 canal 解析 binlog 在写入日志数据库,同步到 es , 完全和业务层解偶,缺点是无法记录用户的 ip 等,不过业务日志只要记录业务行为就行了,剩下的交给系统日志
    taloricag
        3
    taloricag  
    OP
       2021-11-27 09:35:16 +08:00
    @totoro52 谢谢大佬,但是场景不太符合我,因为我的场景不是完全跟业务解耦,还有条件触发,比如修改了 A 字段需要发个邮件,修改了 B 字段发个通知这种,给我整蒙了
    rrfeng
        4
    rrfeng  
       2021-11-27 09:54:20 +08:00 via Android
    gorm 有 hooks 啊
    cs419
        5
    cs419  
       2021-11-27 09:58:52 +08:00
    client 驱动层
    修改 github.com/go-sql-driver/mysql 进行 aop
    fgwmlhdkkkw
        6
    fgwmlhdkkkw  
       2021-11-27 10:12:30 +08:00 via Android
    只记请求和 sql ,然后再用 sql 解析器,取出来字段。
    MIUIOS
        7
    MIUIOS  
       2021-11-27 11:24:58 +08:00   1
    @taloricag 一样可以 只要你的表设计有更新人这类似的字段,可以取出来在回表去查通知,如果你的表设计没有更新人和创建人那就不行了
    MIUIOS
        8
    MIUIOS  
       2021-11-27 11:27:08 +08:00
    @taloricag canal 本身只是负责解析记录,剩下的逻辑还是在自己手上
    Fule
        9
    Fule  
       2021-11-29 09:58:47 +08:00
    SQL Server 2016+ 有 Temporal Table ,自动维护整行历史记录,一定程度上有助于这类问题,不知道其它数据库是否有类似特性:
    https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2016
    shigella
        10
    shigella  
       2021-11-29 10:00:03 +08:00
    canal
    cnit
        11
    cnit  
       2021-11-29 16:28:51 +08:00
    ``` java


    @Component
    @CanalTable("table_name")
    public class OrderHeaderHandler implements EntryHandler {

    @Autowired
    private XxxService xxxService;

    @Override
    public void update(Map<String, String> before, Map<String, String> after, Set<String> updateColumns) {
    //获取需要记录日志的列
    Map<String, String> filedMap = FieldUtils.objectToMap(TableName.class, updateColumns);
    String tableId= before.get("tableId");
    String records = "";
    if (filedMap != null && filedMap.keySet().size() > 0) {
    for (String update : filedMap.keySet()) {
    String comment = filedMap.get(update);
    String beforeValue = before.get(update);
    String afterValue = after.get(update);
    records = records.concat(String.format("%s 由 %s 改为 %s", comment, StringUtils.isEmpty(beforeValue) ? "空" : beforeValue
    , StringUtils.isEmpty(afterValue) ? "空" : afterValue) + ";");
    }
    //记录日志
    OperationRecords operatiOnRecords= new OperationRecords();
    operationRecords.setLinkedId(Long.parseLong(orderId));
    operationRecords.setRecords(records);
    operationRecords.setTableName("container_transport_order_header");
    operationRecords.setCreateTime(new Date());
    operationRecords.setCreateUserId(parseLongUserId(after.get("updateUserId")));
    operationRecordsService.save(operationRecords);
    }
    }



    ```
    onhao
        12
    onhao  
       2021-11-29 17:00:00 +08:00
    @taloricag 我的方案,可能应用场景有限 用触发器
    https://wuhao.pw/archives/268/

    免去了在应用端敲代码了,仅供参考。
    U87
        13
    U87  
       109 天前
    @totoro52 我们业务每个表都有更新人,更新时间,这个可以再回去查没事,ip 等信息咋办,我想到可以塞到 redis 里,把 binlog 解析的内容写到表里的时候,同时去拿 rerdis 里 ip 等信息
    MIUIOS
        14
    MIUIOS  
       109 天前
    @U87 你可以根据更新人的登录 IP 去查询,当然前提是有记录登录 IP
    U87
        15
    U87  
       108 天前
    @totoro52 这个简单,现在比较麻烦的是,产品的需求是查用户这次修改了哪些表的哪些字段,比如这次请求,改了 10 张表,查的时候怎么查,就是怎么关联
    MIUIOS
        16
    MIUIOS  
       108 天前
    @U87 #15 那肯定没办法,binlog 的方式本身就是解耦的, 不带业务逻辑的,你这种最后还是要回归到业务,用 AOP 去做最合适了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2695 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 02:27 PVG 10:27 LAX 19:27 JFK 22:27
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86