15 种超赞的 MyBatis 写法

15 种超赞的 MyBatis 写法

MyBatis 是一款功能强大的 ORM 框架,它通过提供灵活的 SQL 映射和动态 SQL 生成方式,帮助开发者在 Java 程序中高效地与数据库进行交互。
在 MyBatis 中,有许多技巧和写法可以让我们更好地管理和优化数据库操作。
本文将介绍 15 种常见且实用的 MyBatis 写法,提升代码质量与性能,并以代码实例为基础进行解释,最后进行逻辑分析。

1. 使用动态 SQL 生成复杂查询

动态 SQL 允许根据传入的参数生成不同的 SQL 语句,避免了复杂条件下的 SQL 拼接问题。
<select id="selectUsersByCondition" parameterType="map" resultType="User">    SELECT * FROM users WHERE 1=1    <if test="username != null">AND username = #{username}if>    <if test="age != null">AND age = #{age}if>    <if test="status != null">AND status = #{status}if>select>
逻辑分析:动态 SQL 提供了灵活的查询条件,使得 SQL 语句能够根据需求动态变化,减少了冗余的代码。

2. 使用 foreach 实现批量操作

对于批量查询或批量插入,可以使用 foreach 标签来生成批量 SQL。
"batchInsert" parameterType="list">    INSERT INTO users (username, age)    VALUES    <foreach collection="list" item="user" separator=",">        (#{user.username}, #{user.age})    foreach>
逻辑分析:foreach 提供了一种简便的方式来处理批量数据的插入或更新,减少了多次调用的性能消耗。

3. 使用 resultMap 映射复杂结果

当查询返回的列与实体类的字段名称不一致时,resultMap 可以帮忙进行映射。
<resultMap id="userResultMap" type="User">    <id property="id" column="user_id"/>    <result property="username" column="user_name"/>    <result property="age" column="user_age"/>resultMap>
<select id="selectUser" resultMap="userResultMap"> SELECT user_id, user_name, user_age FROM users WHERE user_id = #{id}select>
逻辑分析:resultMap 使得 SQL 结果与 Java 对象之间的映射变得更加灵活和清晰,适用于复杂的查询结果。

4. 分页查询的实现

使用分页插件(如 MyBatis-Plus 或 PageHelper)简化分页查询。
Page<User> page = new Page<>(1, 10);  // 第 1 页,10 条数据List<User> users = userMapper.selectPage(page, new QueryWrapper<>());
逻辑分析:分页插件自动处理分页逻辑,减少了手动拼接 LIMIT 和 OFFSET 的繁琐工作,提升了分页查询的效率。

5. 处理一对多关系

使用 resultMap 的 collection 标签处理一对多关系。
<resultMap id="userWithOrders" type="User">    <id property="id" column="user_id"/>    <result property="username" column="user_name"/>    <collection property="orders" ofType="Order">        <id property="id" column="order_id"/>        <result property="amount" column="order_amount"/>    collection>resultMap>
<select id="selectUserWithOrders" resultMap="userWithOrders"> SELECT u.user_id, u.user_name, o.order_id, o.order_amount FROM users u LEFT JOIN orders o ON u.user_id = o.user_idselect>
逻辑分析:collection 标签帮助我们实现了一对多的查询关系,自动将结果封装到父对象中,方便后续处理。

6. 使用 @Mapper 注解与 XML 配合

通过 @Mapper 注解简化接口的配置,并与 XML 配合使用。
@Mapperpublic interface UserMapper {    List selectUsersByCondition(Map params);}<select id="selectUsersByCondition" parameterType="map" resultType="User">    SELECT * FROM users WHERE username = #{username} AND age = #{age}select>
逻辑分析:@Mapper 注解让接口与 SQL 映射文件更自然地结合,提高了代码的可维护性与清晰度。

7. 批量更新操作

通过 foreach 批量更新数据,提高执行效率。
"batchUpdateUsers" parameterType="list">    <foreach collection="list" item="user" separator=";">        UPDATE users        SET username = #{user.username}, age = #{user.age}        WHERE id = #{user.id}    foreach>
逻辑分析:foreach 的使用能够有效地减少数据库操作的次数,批量更新带来更高的性能。

8. 使用 bind 处理复杂表达式

使用 bind 处理复杂的字符串拼接和计算逻辑。
"pattern" value="'%' + keyword + '%'"/><select id="selectUsersByKeyword" resultType="User">    SELECT * FROM users WHERE username LIKE #{pattern}select>
逻辑分析:bind 标签帮助我们在 SQL 中进行表达式计算,减少了 Java 中的拼接操作,使 SQL 更加简洁。

9. 自定义类型处理器

当 Java 类型与数据库类型不一致时,可以自定义类型处理器。
@MappedJdbcTypes(JdbcType.VARCHAR)@MappedTypes(CustomType.class)public class CustomTypeHandler extends BaseTypeHandler<CustomType> {    @Override    public void setNonNullParameter(PreparedStatement ps, int i, CustomType parameter, JdbcType jdbcType) throws SQLException {        ps.setString(i, parameter.toString());    }
@Override public CustomType getNullableResult(ResultSet rs, String columnName) throws SQLException { return new CustomType(rs.getString(columnName)); }}
逻辑分析:自定义类型处理器解决了数据库和 Java 类型之间的不匹配问题,使得转换变得更加灵活。

10. 实现逻辑删除

使用逻辑删除替代物理删除,保留数据历史。
<update id="deleteUser" parameterType="int">    UPDATE users SET deleted = 1 WHERE id = #{id}update>
逻辑分析:逻辑删除是一种常见的方案,可以在不删除数据的情况下,标记数据为已删除,便于后续恢复。

11. 分表策略

通过动态生成表名来实现分表查询。
<select id="selectFromTable" resultType="User">    SELECT * FROM ${tableName} WHERE id = #{id}select>
逻辑分析:分表策略能够提升数据库性能,适用于海量数据的场景。使用动态 SQL 实现表名切换时,需要特别注意 SQL 注入的防范。

12. 复用 SQL 片段

通过 sql 标签重用 SQL 片段,减少重复代码。
<sql id="baseUserColumns">    id, username, age, emailsql>
<select id="selectUsers" resultType="User"> SELECT <include refid="baseUserColumns"/> FROM usersselect>
逻辑分析:复用 SQL 片段能够提升代码的可维护性,避免了 SQL 语句的重复编写。

13. 处理枚举类型

通过 EnumTypeHandler 将枚举类型与数据库字段映射。
@EnumTypeHandler(EnumTypeHandler.class)public enum UserStatus {    ACTIVE, INACTIVE;}
逻辑分析:枚举类型处理器简化了枚举与数据库之间的映射,代码更加优雅且易于理解。

14. 多数据源支持

在项目中使用多数据源进行数据分离,确保高效的数据管理。
@Configurationpublic class MyBatisConfig {    @Bean    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();        factoryBean.setDataSource(dataSource);        return factoryBean.getObject();    }}
逻辑分析:多数据源支持让我们能够更好地管理不同的数据源,适用于微服务架构和复杂数据需求的场景。

15. 延迟加载

延迟加载可以提高性能,按需加载关联数据。
<settings>    <setting name="lazyLoadingEnabled" value="true"/>settings>
逻辑分析:延迟加载通过懒加载关联数据,避免不必要的查询,优化了性能。

总结


MyBatis 提供了多种灵活的功能,帮助开发者高效地进行数据库操作。
通过使用动态 SQL、批量操作、resultMap、分页查询等技巧,开发者可以有效地简化 SQL 代码并提升查询性能。
同时,MyBatis 支持自定义类型处理器、逻辑删除、分表策略等高级功能,适用于复杂的业务需求。
掌握这些常见的 MyBatis 写法,不仅能够提升开发效率,还能确保系统在大数据量和复杂场景下的高效运行。

? 大家好,我是枫哥,一名Java后端开发者!

我热衷于探索新技术,并在我的微信公众号上分享关于Java 生态和后端开发的知识。

欢迎关注我的公众号,期待与你一起探讨技术的无穷可能!目前专注于Java技术分享,覆盖春招、秋招、社招和跳槽相关内容,并提供一对一带徒学习服务。

加入 学徒计划,即可享受内推机会和优质资源,签订协议确保就业无忧。

此外,我们还推出了‘Java跳槽网’, 为你的求职之路提供全方位支持,助你快速找到理想工作


END


请使用浏览器的分享功能分享到微信等