请教一个 SQL 改写问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Wh1te
V2EX    Java

请教一个 SQL 改写问题

  •  
  •   Wh1te 2023 年 2 月 13 日 2398 次点击
    这是一个创建于 1168 天前的主题,其中的信息可能已经有所发展或是发生改变。
    背景:用户表目前明文存储着用户的姓名、手机号等等,现在需要改为密文存储。

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

    问题:历史数据量比较大,在刷数据时存在这样一段过度时期是明文和密文同时存在的(旧数据是明文,新写入的数据是密文),手机号在业务上又是有精确查询的需求,很多 SQL 都有 mobile = 'xxxxxx' 的查询条件,在过度时期也要保证这些 SQL 能查到正确的数据,目前想到的办法是用 mybatis 的插件修改 SQL ,将 mobile = '明文' 改写成 mobile in ('明文', '密文'),等过渡时期结束后再去掉这个插件。那么问题来了,这样的 SQL 改写需求有没有什么方便快捷的实现方案呢?
    16 条回复    2023-02-19 12:46:44 +08:00
    ProgrammerAlan
        1
    ProgrammerAlan  
       2023 年 2 月 13 日
    public class CustomSQLInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler statementHandler = (StatementHandlr) 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 年 2 月 13 日
    @ProgrammerAlan ChatGPT 给出的答案,使用 Mybatis 拦截器改写 SQL
    paopjian
        3
    paopjian  
       2023 年 2 月 13 日   1
    为什么不新建一张表,新数据放新表,旧数据修改好后再放新表里,最后删除?
    jomalonejia
        4
    jomalonejia  
       2023 年 2 月 13 日
    新字段 or 新表 先保证库里有数据 再调整业务逻辑 over
    blubzz
        5
    blubzz  
       2023 年 2 月 13 日
    建议表新增加密字段,代码增加双写逻辑,同时保存明文和密文,但查询逻辑还是用明文字段。
    然后历史数据加密跑批,最后再切换使用密文查询。
    sxfscool
        6
    sxfscool  
       2023 年 2 月 13 日
    加新字段吧
    Wh1te
        7
    Wh1te  
    OP
       2023 年 2 月 13 日
    @paopjian #3
    @jomalonejia #4
    @blubzz #5
    @sxfscool #6

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

    `
    where mobile = encrypt_mobile('xxxxxx')

    encrypt_mobile 是个 function 写到 database 里面, 或者利用 database 已有的函数.
    `
    echoless
        15
    echoless  
       2023 年 2 月 18 日
    上面的作废, 没读完.br />
    sql 改写 如果你通过的是 orm 可以在 orm 层做. 该 raw sql, 可以解析 sql, 找到有 mobile 筛选条件, 去替换. (如果 sql 不多, 人工更简单吧)
    Wh1te
        16
    Wh1te  
    OP
       2023 年 2 月 19 日
    @wuhaoecho #15 改 raw sql, 可以解析 sql, 找到有 mobile 筛选条件, 去替换.
    我的主要问题就是这个实现的代码写不出来
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2715 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 47ms UTC 07:09 PVG 15:09 LAX 00:09 JFK 03:09
    Do have faith in what you're doing.
    ubao msn 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