MyBatis中的 10 个宝藏技巧!
前言
说到 MyBatis,很多小伙伴都会用,但未必用得“惊艳”。
实际上,这个轻量级的持久层框架还有很多隐藏的“宝藏技巧”。
如果你能掌握这些技巧,不但能让开发更高效,还能避免掉入一些常见的“坑”。
今天就从浅入深,分享 10 个让人眼前一亮的 MyBatis 开发技巧,每一个都配上具体的场景和代码示例,务求通俗易懂,希望对你会有所帮助。
(我最近开源了一个基于 SpringBoot+Vue+uniapp 的商城项目,欢迎访问和star。)[https://gitee.com/dvsusan/susan_mall]
1. 灵活使用动态 SQL
很多小伙伴在写 SQL 的时候,喜欢直接用拼接字符串的方式,比如:
String sql = "SELECT * FROM user WHERE 1=1";
if (name != null) {
sql += " AND name = '" + name + "'";
}
这种写法不仅麻烦,而且安全性很差(容易引发 SQL 注入)。
MyBatis 的动态 SQL 是专门为解决这种问题设计的,你可以用 if、choose、foreach 等标签来动态构造 SQL。
示例:动态条件查询
<select id="findUser" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
这个代码的好处是,SQL 逻辑清晰,不会因为某个参数为空就导致整个 SQL 报错。
2. 善用 resultMap 自定义结果映射
有些小伙伴会遇到这样的问题:数据库表字段是下划线命名,但 Java 对象是驼峰命名。比如 user_name 对应 userName。如果直接用默认的 resultType,MyBatis 是无法自动映射的。
这个时候,用 resultMap 就能完美解决。
示例:自定义结果映射
<resultMap id="userResultMap" type="User">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="age" property="age"/>
</resultMap>
<select id="getUserById" resultMap="userResultMap">
SELECT id, user_name, age FROM user WHERE id = #{id}
</select>
有了 resultMap,再复杂的字段映射都可以轻松搞定。
3. 利用 foreach 实现批量操作
有些小伙伴可能会遇到这种需求:传入一个 ID 列表,查询所有匹配的用户信息。如果用拼接字符串的方式生成 IN 条件,不但代码丑,还容易踩坑。
MyBatis 提供了 foreach 标签,可以优雅地处理这种场景。
示例:批量查询
<select id="findUsersByIds" resultType="User">
SELECT * FROM user WHERE id IN
<foreach item="id" collection="idList" open="(" separator="," close=")">
#{id}
</foreach>
</select>
传入的 idList 是一个 List 或数组,MyBatis 会自动帮你展开为 IN (1, 2, 3) 这样的格式,完全不用担心语法问题。
4. MyBatis-Plus 的分页功能
很多小伙伴在做分页的时候,习惯自己写 LIMIT 的 SQL,这样不仅麻烦,还容易出错。
其实,用 MyBatis-Plus 的分页插件能省不少事。
示例:MyBatis-Plus 分页功能
Page<User> page = new Page<>(1, 10); // 第 1 页,每页 10 条
IPage<User> userPage = userMapper.selectPage(page, null);
System.out.println("总记录数:" + userPage.getTotal());
System.out.println("当前页数据:" + userPage.getRecords());
只需引入分页插件,就能轻松完成分页操作,简直不要太爽。
5. 使用 @Mapper的接口代理
有些小伙伴觉得 XML 文件太多太麻烦,其实 MyBatis 支持纯注解的开发模式,尤其是对于简单的 SQL,非常方便。
示例:注解方式查询
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User getUserById(int id);
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
void addUser(User user);
}
用这种方式,可以完全省掉 XML 配置,代码更加简洁。
6. 二级缓存
MyBatis 内置了一级缓存(SqlSession 范围内),但对于多次查询的场景,可以开启二级缓存来提升性能。
示例:开启二级缓存
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
<mapper namespace="com.example.mapper.UserMapper">
<cache/>
<select id="getUserById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
开启二级缓存后,同一个 Mapper 下的查询会自动命中缓存,大幅提高性能。
7. 动态表名切换
有些多租户系统需要在运行时切换表名,比如按租户分表。这种情况下,可以用 MyBatis 的动态 SQL 特性来实现。
示例:动态表名
<select id="getDataFromDynamicTable" resultType="Map">
SELECT * FROM ${tableName} WHERE id = #{id}
</select>
在调用时传入 tableName 参数,MyBatis 会动态替换表名。
8. 用 typeHandler 自定义类型处理
有些小伙伴可能遇到过这种场景:数据库存的是 1/0,但在代码里想用 true/false 表示。
这种情况可以通过自定义 typeHandler 来实现。
示例:自定义 TypeHandler
@MappedTypes(Boolean.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class BooleanTypeHandler extends BaseTypeHandler<Boolean> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter ? 1 : 0);
}
@Override
public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getInt(columnName) == 1;
}
}
在 MyBatis 配置中注册这个 typeHandler,就可以实现自动类型转换了。
9. 日志调试,快速排查问题
开发中经常需要排查 SQL 执行的问题,这时 MyBatis 的日志功能非常好用。
通过配置,可以轻松打印出完整的 SQL 和参数。
示例:开启日志
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
</configuration>
日志会输出类似下面的内容:
==> Preparing: SELECT * FROM user WHERE id = ?
==> Parameters: 1(Integer)
<== Total: 1
有了这些日志,排查问题再也不头疼了。
10. 多数据源支持
当系统需要连接多个数据库时,可以通过 MyBatis 的多数据源配置轻松搞定。
示例:配置多数据源
@Configuration
@MapperScan(basePackages = "com.example.mapper", sqlSessionTemplateRef = "sqlSessionTemplate1")
public class DataSourceConfig1 {
@Bean(name = "dataSource1")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactory1")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "sqlSessionTemplate1")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
通过类似的配置,就可以轻松切换多个数据源。
总结
MyBatis 的魅力在于简单、高效,但很多时候我们用得太“基础”,没有发挥它的全部潜力。
希望这 10 个技巧能帮你更高效地使用 MyBatis,也让你的代码看起来更“惊艳”。
如果觉得有帮助,记得收藏分享!
最后说一句(求关注,别白嫖我)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
MyBatis中的 10 个宝藏技巧!的更多相关文章
- 记录一次bug解决过程:mybatis中$和#的使用
一.总结 mybatis中使用sqlMap进行sql查询时,经常需要动态传递参数.动态SQL是mybatis的强大特性之一,也是它优于其他ORM框架的一个重要原因.mybatis在对sql语句进行预编 ...
- 10 个实用技巧,让 Finder 带你飞
Finder 是 Mac 电脑的系统程序,有的功能类似 Windows 的资源管理器.它是我们打开 Mac 首先见到的「笑脸」,有了它,我们可以组织和使用 Mac 里的几乎所有东西,包括应用程序.文件 ...
- Mybatis中的collection、association来处理结果映射
前不久的项目时间紧张,为了尽快完成原型开发,写了一段效率相当低的代码. 最近几天闲下来,主动把之前的代码优化了一下:) 标签:Java.Mybatis.MySQL 概况:本地系统从另外一个系统得到 ...
- 161102、MyBatis中批量插入
方法一: <insert id="insertbatch" parameterType="java.util.List"> <selectKe ...
- UE中使用正则表达式的一些技巧
UE中使用正则表达式的一些技巧 2010-12-24 10:33:19 分类: Linux 以下是网上摘录的UE 技巧 1)删除空行: 替换 %[ ^t]++^p 为 空串 2)删除行尾空格: 替换 ...
- Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理
Mybatis特殊字符处理,Mybatis中xml文件特殊字符的处理 >>>>>>>>>>>>>>>>& ...
- Visual Studio 原生开发的10个调试技巧(二)
原文:Visual Studio 原生开发的10个调试技巧(二) 我以前关于 Visual Studio 调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识.以下的列表中你可以看到写原 ...
- ★10 个实用技巧,让Finder带你飞~
10 个实用技巧,让 Finder 带你飞 Finder 是 Mac 电脑的系统程序,有的功能类似 Windows 的资源管理器.它是我们打开 Mac 首先见到的「笑脸」,有了它,我们可以组织和使用 ...
- ★10 个实用技巧,让Finder带你飞~
10 个实用技巧,让 Finder 带你飞 Finder 是 Mac 电脑的系统程序,有的功能类似 Windows 的资源管理器.它是我们打开 Mac 首先见到的「笑脸」,有了它,我们可以组织和使用 ...
- Mybatis中常用的SQL
1.BaseResultMap <resultMap id="BaseResultMap" type="com.stylefeng.guns.common.pers ...
随机推荐
- win10下端口映射设置内网别人访问本机安装的vmware默认NAT网络
用管理员权限打开powershell或者cmd,命令如下 netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=主 ...
- My SQL 列转行操作
原表结构如下,我们可以发现,"日运输量"和"车次"是在同一张表中相互独立的两个字段,即独立的两列数据,下面,我将系统中的测试数据以及代码全部放出来,以解释列转行 ...
- DFS序求LCA
DFS序求LCA 介绍 欧拉序求LCA 的数组总是会忘记开两倍,并且预处理的常数较大.用 DFS序求LCA 可以解决这些问题. 欧拉序:进节点和出节点会重复记录节点. DFS序:深度优先搜索的顺序,不 ...
- c++11新增内容
记录一下c++11新特性方便以后回忆 1.nullptr (对标NULL) 2.auto ,decltype(根据表达式推断类型,表达式不执行) decltype(func()) sum = 5; / ...
- C++入门级基础知识汇总
知识来源:https://www.imooc.com/learn/1304 https://www.runoob.com/cplusplus/cpp-tutorial.html 编程第一步导入头文件: ...
- WebService WCF 请求通道在等待 00:00:58.9616639 以后答复时超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能是更长超时的一部分。
查看使用什么方式调用的接口 如果是使用的 HttpWebRequest 请检查Timeout属性,默认值是 100,000 毫秒(100 秒)如果超过便会返回超时错误.
- 高性能计算-openmp-多线程缓存一致性(9)
1. 背景介绍 L1 L2 cache是单核独享,L3是多核共享.如果多线程访问共享一维数组的连续元素,先读入第一个线程的L1 缓存中,其他线程访问缓存不命中需要加载,并且数据的更改后,标记为脏数据, ...
- 数字IC知识点:处理多个时钟
1. 多时钟域 图1.多时钟域 对于工程师来说,开发含多个时钟(见图1)的设计是一种挑战. 这样的设计中可能有以下任何一个,或者全部类型的时钟关系: 时钟的频率不同 时钟频率相同,但相位不同 以上两种 ...
- 方法的虚分派(virtual dispatch)和方法表(method table)
Java方法调用的虚分派 JUN 2ND, 2013 | COMMENTS 本文通过介绍 Java 方法调用的虚分派,来加深对 Java 多态实现的理解.需要预先理解 Java 字节码和 JVM 的基 ...
- 基于JDBC的数据库连接池高效管理策略
在基于JDBC的数据库应用开发中,数据库连接的管理是一个难点,因为它是决定该应用性能的一个重要因素.本文在对数据库连接进行透彻分析的基础上,提出并实现了一个高效的连接管理策略,使得开发高性能的数据库应 ...