【Mybatis】Mybatis还能这么玩?整的我一脸懵逼。。。
开篇词:
这期给大家分享一个关于 MyBatis 的“编程小技巧”,说真的,这骚操作,直接整的我一脸懵逼。。。
干货篇:
按秒杀场景举例:
service层的代码肯定有如下逻辑
1.保存订单
2.更新库存
1.分分钟能写出这样的伪代码:
public void seckill() {
//开启事务
begin;
1.保存订单
service.save();
2.更新库存
service.update();
if (checkIfSuccess()) {
//提交事务
commit;
} else {
//回滚事务
rollback
}
}
现在我给你展示一下用“编程小技巧”写出来的真实的代码。
2.别····眨····眼~~
这就是一个 MyBatis 的 mapper 接口,接下来就直接到了 mapper.xml 文件里面:
这写法,这小技巧,我都不打算问你骚不骚,我就问你见没见过?
3.关键是真能用吗?
秉承着大胆假设小心求证的态度,本地自测了一波~~
项目启动之后发起调用,控制台直接报了错:
看到这个报错的时候,我下意识的觉得就是 MyBatis 不支持这样的写法,直接报错了,这也符合我的预期
4.有意思的事情发生了
但是如果配置了如下属性
allowMultiQueries=true
无报错且正确执行了 insert 和 update!!!!
对于这个参数,查阅了官网:
Allow the use of “;” to delimit multiple queries during one statement. This option does not affect the ‘addBatch()’ and ‘executeBatch()’ methods, which rely on ‘rewriteBatchStatements’ instead.
允许在一条语句中使用"; "分隔多个查询。该选项不会影响 "addBatch() "和 "executeBatch() "方法,因为它们依赖于 “rewriteBatchStatements”。
在介绍 allowMultiQueries 的时候,还提到了一个
5.rewriteBatchStatements 参数。
关于这个参数,简单简单介绍一下:
- rewriteBatchStatements 参数并不是直接关联于 MyBatis 的一个配置选项,但它经常与 JDBC 驱动(尤其是 MySQL JDBC 驱动)和 MyBatis 的批量操作一起被提及。这个参数实际上是 MySQL JDBC 驱动中的一个特性,用于优化批量插入(INSERT)、更新(UPDATE)和删除(DELETE)操作的性能。
- MySQL JDBC 驱动的 rewriteBatchedStatements
在 MySQL JDBC 驱动中,rewriteBatchedStatements 是一个连接字符串(URL)参数,用于启用或禁用对批量语句的重写。当设置为 true 时,MySQL JDBC 驱动会尝试将多个单独的 INSERT、UPDATE 或 DELETE 语句组合成一个批量语句发送给 MySQL 服务器,以减少网络往返次数和提高性能。这对于大量数据的批量操作特别有用。 - 如何设置
在 JDBC 连接字符串中设置 rewriteBatchedStatements=true。例如,如果你使用的是 MySQL 数据库,你的连接字符串可能看起来像这样:
java
复制代码
jdbc:mysql://localhost:3306/yourdatabase?rewriteBatchedStatements=true
MyBatis 与 rewriteBatchedStatements
- 虽然 rewriteBatchedStatements 是 JDBC 驱动级别的配置,但 MyBatis 通过其底层使用的 JDBC 连接来利用这一特性。当你在 MyBatis 中执行批量操作时(比如使用 标签在 MyBatis 映射文件中构造多个 INSERT 语句,或者使用 MyBatis 的 SqlSession.insertList 方法等),如果 JDBC 连接字符串中启用了 rewriteBatchedStatements,那么 MyBatis 的这些批量操作就能更有效地执行。
- 注意事项
rewriteBatchedStatements 并不总是能完全优化所有类型的批量操作。它主要对 INSERT、UPDATE 和 DELETE 语句有效,而对于 SELECT 语句则没有直接影响。 - 在某些情况下,使用 rewriteBatchedStatements 可能会导致性能下降,特别是在处理大量小事务时。因此,建议根据你的具体应用场景进行测试。
- 启用 rewriteBatchedStatements 可能会改变 SQL 语句的发送方式,这可能会影响到一些基于 SQL 日志的监控工具或数据库审计工具的行为。
6.扩展
题外话,请问是“订单加一,库存减一”的性能好,还是“库存减一,订单加一”的性能好,还是说这二者没有什么区别?
- 首先,从执行结果上看,这二者确实是没有什么区别的,都能保证业务场景的正确性。
- 但是当你考虑性能的时候,肯定是“订单加一,库存减一”的性能更好。
- 因为 where 条件中是 id=1,所以锁是加在唯一索引上的,而且表中存在该记录,所以只会对 id=1 这行记录加锁。
针对 id=1 这一个产品来说,如果它是一个热点商品,我们采取“订单加一,库存减一”的写法,性能会更高一点。
在加锁频率相同的情况下,解锁越快的,性能越高。
上个图你就明白了:
总结篇:
- 首先这样的写法就不符合绝大部分程序员的认知。
- 谁能想到mapper.xml 里面居然还埋在一坨业务逻辑呢?
- 知道就好,生产别这么干!谨记!!!