V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Wh1te
V2EX  ›  Java

请教一个 SQL 改写问题

  •  
  •   Wh1te · 2023-02-13 14:52:54 +08:00 · 1887 次点击
    这是一个创建于 679 天前的主题,其中的信息可能已经有所发展或是发生改变。
    背景:用户表目前明文存储着用户的姓名、手机号等等,现在需要改为密文存储。

    方案:使用 mybatis 的插件功能,修改参数,将需要加密的字段加密后再执行。上线后清洗数据,将历史明文数据刷为密文。

    问题:历史数据量比较大,在刷数据时存在这样一段过度时期是明文和密文同时存在的(旧数据是明文,新写入的数据是密文),手机号在业务上又是有精确查询的需求,很多 SQL 都有 mobile = 'xxxxxx' 的查询条件,在过度时期也要保证这些 SQL 能查到正确的数据,目前想到的办法是用 mybatis 的插件修改 SQL ,将 mobile = '明文' 改写成 mobile in ('明文', '密文'),等过渡时期结束后再去掉这个插件。那么问题来了,这样的 SQL 改写需求有没有什么方便快捷的实现方案呢?
    16 条回复    2023-02-19 12:46:44 +08:00
    ProgrammerAlan
        1
    ProgrammerAlan  
       2023-02-13 15:51:17 +08:00
    public class CustomSQLInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = statementHandler.getBoundSql();
    String sql = boundSql.getSql();

    if (sql.contains("mobile =")) {
    // 对 SQL 进行修改
    sql = sql.replace("mobile =", "mobile in");
    sql = sql.replace("'", "('");
    sql = sql + "', '密文')";

    // 使用新的 SQL
    Field field = boundSql.getClass().getDeclaredField("sql");
    field.setAccessible(true);
    field.set(boundSql, sql);
    }

    return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
    if (target instanceof StatementHandler) {
    return Plugin.wrap(target, this);
    }
    return target;
    }

    @Override
    public void setProperties(Properties properties) {
    }
    }
    ProgrammerAlan
        2
    ProgrammerAlan  
       2023-02-13 15:54:29 +08:00
    @ProgrammerAlan ChatGPT 给出的答案,使用 Mybatis 拦截器改写 SQL
    paopjian
        3
    paopjian  
       2023-02-13 16:00:35 +08:00   ❤️ 1
    为什么不新建一张表,新数据放新表,旧数据修改好后再放新表里,最后删除?
    jomalonejia
        4
    jomalonejia  
       2023-02-13 16:09:01 +08:00
    新字段 or 新表 先保证库里有数据 再调整业务逻辑 over
    blubzz
        5
    blubzz  
       2023-02-13 16:18:00 +08:00
    建议表新增加密字段,代码增加双写逻辑,同时保存明文和密文,但查询逻辑还是用明文字段。
    然后历史数据加密跑批,最后再切换使用密文查询。
    sxfscool
        6
    sxfscool  
       2023-02-13 16:23:41 +08:00
    加新字段吧
    Wh1te
        7
    Wh1te  
    OP
       2023-02-13 17:59:53 +08:00
    @paopjian #3
    @jomalonejia #4
    @blubzz #5
    @sxfscool #6

    实际需求有几十个表,几十个字段,而且历史数据量比较大,感觉加新表新字段做起来也挺麻烦的😂
    Wh1te
        8
    Wh1te  
    OP
       2023-02-13 18:00:40 +08:00
    @ProgrammerAlan #1 这个直接字符串替换感觉不太行,如果 SQL 有个换行或者用了别名联表啥的,就 GG 了
    heysnakelis
        9
    heysnakelis  
       2023-02-13 18:06:35 +08:00
    根据手机号码的最后一个数字 逐步清洗,先清尾号 1 的数据,然后写 sql 的时候如果尾号 1 就走加密查询,尾号不是就原手机号查询,分配清洗替换?
    season8
        10
    season8  
       2023-02-13 18:20:46 +08:00
    如你所说,就一个用户表需要加密,那代码量应该不多吧,硬改工作量应该还好,就硬改呗。
    Wh1te
        11
    Wh1te  
    OP
       2023-02-13 18:43:00 +08:00
    @season8 #10 不好意思,主贴没有写清楚,只是拿一个用户表举例,实际需求是有几十表存在这样的数据需要处理😧
    dog82
        12
    dog82  
       2023-02-14 10:46:26 +08:00
    2 楼说的用拦截器是个好思路,就是不知道拦截规则怎么定义
    Wh1te
        13
    Wh1te  
    OP
       2023-02-15 22:38:35 +08:00
    @dog82 #12 是的,我说的 mybatis 插件就是 mybatis 的拦截器,我想问的是这个 SQL 改写逻辑要怎么实现
    echoless
        14
    echoless  
       2023-02-18 16:08:54 +08:00
    @Wh1te 手机号在业务上又是有精确查询的需求,很多 SQL 都有 mobile = 'xxxxxx' 的查询条件

    `
    where mobile = encrypt_mobile('xxxxxx')

    encrypt_mobile 是个 function 写到 database 里面, 或者利用 database 已有的函数.
    `
    echoless
        15
    echoless  
       2023-02-18 16:14:13 +08:00
    上面的作废, 没读完.

    sql 改写 如果你通过的是 orm 可以在 orm 层做. 该 raw sql, 可以解析 sql, 找到有 mobile 筛选条件, 去替换. (如果 sql 不多, 人工更简单吧)
    Wh1te
        16
    Wh1te  
    OP
       2023-02-19 12:46:44 +08:00
    @wuhaoecho #15 改 raw sql, 可以解析 sql, 找到有 mobile 筛选条件, 去替换.
    我的主要问题就是这个实现的代码写不出来 😂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1639 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:42 · PVG 00:42 · LAX 08:42 · JFK 11:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.