Mybatis Plugin 以及Druid Filer 改写SQL

背景

工作中偶尔会碰到需要统一修改SQL的情况,例如有以下表结构:

CREATE TABLE `test_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account` varchar(70) NOT NULL COMMENT '账号',
  `user_name` varchar(60) NOT NULL COMMENT '姓名',
  `age` int(11) NOT NULL COMMENT '年龄',
  `sex` bit(1) NOT NULL COMMENT '性别:0-男,1-女',
  `create_time` timestamp NOT NULL DEFAULT '2019-01-01 00:00:00' COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_account` (`account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';

假设有如下Mapper SQL:

insert into `test_user`(`account`, `user_name`, `age`, `sex`, `create_time`)
values ('test1', 'test_user_1', 1, 0, now())
on duplicate key update 
`user_name` = 'test_user_1', `age` = 1, `sex` = 0;

在Service层代码中通过判断Mapper返回的影响行数是否等于1来识别SQL是否执行成功。但假如duplicate key update设置的字段值和数据库中的记录值完全一致,则mysql不会执行update,因此在JDBC返回的影响行数会为0,导致Service层逻辑错误。

解决方法很简单,只需在duplicate key update中加上update_time = now()即可,但如果这种语句广泛存在,那么最简单的方法就是通过SQL Rewrite来实现。

设计 & 选型

何时修改SQL

系统使用Mybatis作为ORM,alibaba druid作为数据库连接池。

Mybatis提供了plugin机制来修改SQL,例如Mybatis-PageHelper就是使用plugin机制修改SQL添加分页和Count语句。

Druid提供了Filter机制来修改SQL,例如EncodingConvertFilter就是使用了Filter机制在实际执行前执行了编码转换。

既然以上两者都能做到修改SQL,那么我们该选择在什么时候执行修改呢?其实这两者并没有什么显著的优劣区别,我个人来看有以下两点区别:

  1. 可移植性不同。比如JDBC连接池使用的是Hikari或者DBCP,这个时候更适合在Mybatis层修改,反过来如果ORM框架选择的是Hibernate则druid更适合。
  2. 工作量不同。因为ORM和JDBC的代码抽象程度不同导致了在不同层面执行改写工作量有较大差异,基于Mybatis的ORM层进行改写时工作量远小于基于Druid的JDBC层改写,因为JDBC更底层,要考虑的更多,例如执行模式是PreparedStatment还是Statement,或者是CallableStatement等,改写时需要将这些全部覆盖到,而ORM层的改写则不用考虑这么细。

SQL Parser选型

要改写SQL,首先得先解析SQL,分析SQL的语义来判断是否需要改写以及改写哪一部分,而词法分析历来是非常耗时的,因此SQL Parser框架很重要。Java生态中较为流行的SQL Parser有以下几种:

  • fdb-sql-parser 是FoundationDB在被Apple收购前开源的SQL Parser,目前已无人维护。
  • jsqlparser 是基于JavaCC的开源SQL Parser,是General SQL Parser的Java实现版本。
  • Apache calcite 是一款开源的动态数据管理框架,它具备SQL解析、SQL校验、查询优化、SQL生成以及数据连接查询等功能,常用于为大数据工具提供SQL能力,例如Hive、Flink等。calcite对标准SQL支持良好,但是对传统的关系型数据方言支持度较差。
  • alibaba druid 是阿里巴巴开源的一款JDBC数据库连接池,但其为监控而生的理念让其天然具有了SQL Parser的能力。其自带的Wall Filer、StatFiler等都是基于SQL Parser解析的AST。并且支持多种数据库方言。

其实说到SQL Rewrite,我们很容易就想到数据库中间件的分库分表,因此我们在选择SQL Parser时完全可以参考那些知名的数据库中间件。Apache Sharding Sphere(原当当Sharding-JDBC)Myca

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis接入Druid是指在使用MyBatis框架时,使用Druid作为连接池来连接数据库。Druid是一个开源的Java数据库连接池,具有监控、防御SQL注入等功能。在MyBatis中接入Druid可以提供更好的数据库连接管理和性能监控。 在引用\[1\]中提到了一个简单的Demo演示使用MyBatis+Druid来连接数据库。这个Demo展示了使用MyBatis配置文件和Druid数据源配置文件,以及如何在代码中使用MyBatis的API来进行数据库操作。通过这个Demo,可以了解到MyBatisDruid的基本使用方法和配置。 需要注意的是,MyBatisDruid是两个独立的框架,可以分别学习和使用。MyBatis是一个持久层框架,用于数据库操作,而Druid是一个数据库连接池,用于管理数据库连接。在使用MyBatis时,可以选择是否使用Druid作为连接池,以提高数据库连接的性能和管理。 总结起来,MyBatis接入Druid是指在使用MyBatis框架时,使用Druid作为连接池来连接数据库,以提供更好的数据库连接管理和性能监控。 #### 引用[.reference_title] - *1* *2* *3* [MyBatis技术原理浅析:使用MyBatis+Druid连接MySQL数据库](https://blog.csdn.net/qq_25827845/article/details/95763605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值