MyBatis与MyBatis-Plus的区别

MyBatis 深度解析

核心组件
  1. SqlSessionFactory

    • 作用:创建 SqlSession 对象,是 MyBatis 的核心入口
    • 配置方式:
      • XML 配置(mybatis-config.xml)
      • Java 代码构建(较少使用)
  2. SqlSession

    • 作用:执行 SQL 命令、管理事务
    • 特点:非线程安全,建议每次使用时创建新实例
  3. Executor

    • 作用:执行 SQL 语句,处理缓存
    • 类型:
      • SimpleExecutor:每次执行都会创建新的 Statement
      • ReuseExecutor:重复使用 Statement
      • BatchExecutor:批量执行 SQL
  4. StatementHandler

    • 作用:处理 SQL 语句的预编译、参数设置、结果集映射
配置细节
  1. 全局配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
      </mappers>
    </configuration>
    
  2. 映射文件结构

    <mapper namespace="com.example.mapper.UserMapper">
      <!-- 结果映射 -->
      <resultMap id="BaseResultMap" type="com.example.entity.User">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="age" property="age" jdbcType="INTEGER"/>
      </resultMap>
      
      <!-- 查询语句 -->
      <select id="selectById" resultMap="BaseResultMap">
        SELECT * FROM user WHERE id = #{id}
      </select>
      
      <!-- 插入语句 -->
      <insert id="insert" parameterType="com.example.entity.User">
        INSERT INTO user (name, age) VALUES (#{name}, #{age})
      </insert>
    </mapper>
    
高级特性
  1. 动态 SQL

    • 标签:<if><choose><when><otherwise><where><set><foreach>
    • 示例:
      <select id="findUsers" resultType="User">
        SELECT * FROM user
        <where>
          <if test="name != null">
            AND name = #{name}
          </if>
          <if test="age != null">
            AND age = #{age}
          </if>
        </where>
      </select>
      
  2. 缓存机制

    • 一级缓存:SqlSession 级别
    • 二级缓存:全局级别,跨 SqlSession 共享
    • 配置方式:
      <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
      
  3. 插件机制

    • 可拦截的方法:Executor、ParameterHandler、ResultSetHandler、StatementHandler
    • 示例:
      @Intercepts({@Signature(
        type = Executor.class,
        method = "query",
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
      )})
      public class ExamplePlugin implements Interceptor {
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
          // 增强逻辑
          return invocation.proceed();
        }
      }
      

MyBatis-Plus 深度解析

核心组件
  1. BaseMapper

    • 内置方法:
      int insert(T entity);
      int deleteById(Serializable id);
      int updateById(@Param(Constants.ENTITY) T entity);
      T selectById(Serializable id);
      List<T> selectList(Wrapper<T> queryWrapper);
      
  2. IService

    • 内置方法:
      boolean save(T entity);
      boolean removeById(Serializable id);
      boolean updateById(T entity);
      T getById(Serializable id);
      List<T> list(Wrapper<T> queryWrapper);
      
  3. ServiceImpl

    • 实现 IService 接口,提供基础 CRUD 功能
    • 使用方式:
      @Service
      public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
        // 可扩展自定义方法
      }
      
增强特性
  1. 条件构造器

    • Lambda 表达式方式:
      List<User> userList = userService.list(
        new LambdaQueryWrapper<User>()
          .eq(User::getName, "张三")
          .ge(User::getAge, 18)
          .orderByDesc(User::getCreateTime)
      );
      
  2. 自动填充

    • 实现 MetaObjectHandler 接口:
      @Component
      public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
          this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        }
        
        @Override
        public void updateFill(MetaObject metaObject) {
          this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        }
      }
      
  3. 逻辑删除

    • 实体类字段添加注解:
      @TableLogic
      private Integer deleted;
      
  4. 分页插件

    • 配置类:
      @Configuration
      public class MyBatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
          MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
          interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
          return interceptor;
        }
      }
      
  5. 代码生成器

    • 使用示例:
      FastAutoGenerator.create("jdbc:mysql://localhost:3306/test", "root", "password")
        .globalConfig(builder -> {
          builder.author("baomidou") // 设置作者
            .outputDir("D://mybatis-plus-code"); // 指定输出目录
        })
        .packageConfig(builder -> {
          builder.parent("com.example") // 设置父包名
            .moduleName("module") // 设置模块名
            .pathInfo(Collections.singletonMap(OutputFile.xml, "D://mybatis-plus-code/xml")); // 设置mapperXml生成路径
        })
        .strategyConfig(builder -> {
          builder.addInclude("user") // 设置需要生成的表名
            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
        })
        .execute();
      

性能对比

场景MyBatis 执行时间MyBatis-Plus 执行时间原因分析
单表查询(无复杂条件)约 20ms约 25msMP 有额外的反射和代理开销
单表分页查询约 30ms约 35msMP 分页插件有一定开销
复杂多表联查约 50ms约 55msMP 优势不明显,需手写 SQL
批量插入 1000 条数据约 800ms约 600msMP 内置批量插入优化

最佳实践建议

  1. 项目选型

    • 新项目建议优先考虑 MyBatis-Plus,开发效率更高
    • 遗留项目已有大量 MyBatis 代码,可逐步引入 MyBatis-Plus
  2. 分层设计

    • Controller → Service → Mapper
    • Service 层使用 MyBatis-Plus 的 IService 和 ServiceImpl
    • 复杂查询在 Mapper 层自定义 SQL
  3. 复杂查询处理

    • 方式一:在 Mapper 接口中定义方法,XML 中编写 SQL
    • 方式二:使用 MyBatis-Plus 的 Wrapper 构造复杂条件
    • 方式三:结合 MyBatis-Plus 的 QueryWrapper 和自定义 SQL
  4. 分页处理

    • 单表分页:直接使用 MyBatis-Plus 分页插件
    • 复杂分页:自定义 SQL + 分页插件
  5. 事务管理

    • 使用 Spring 的 @Transactional 注解管理事务
    • 示例:
      @Service
      public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
        @Override
        @Transactional(rollbackFor = Exception.class)
        public boolean saveUserAndLog(User user) {
          // 保存用户
          boolean result = this.save(user);
          // 记录日志
          logService.saveLog("用户注册:" + user.getName());
          return result;
        }
      }
      

常见问题与解决方案

  1. MyBatis 问题

    • 问题:SQL 注入风险
    • 解决方案:使用 #{} 占位符,避免使用 ${}
  2. MyBatis-Plus 问题

    • 问题:复杂查询性能不如纯手写 SQL
    • 解决方案:复杂查询部分使用自定义 SQL
  3. 通用问题

    • 问题:字段映射不一致
    • 解决方案
      • 使用 @TableField 注解
      • 配置全局下划线转驼峰
  4. 分页问题

    • 问题:分页插件不生效
    • 解决方案
      • 检查分页插件是否正确配置
      • 确保调用的是 Page 相关方法
  5. 缓存问题

    • 问题:二级缓存导致数据不一致
    • 解决方案
      • 敏感数据禁用二级缓存
      • 更新数据时及时清除缓存

通过以上对比可以看出,MyBatis-Plus 在保持 MyBatis 核心功能的基础上,显著提升了开发效率,尤其适合以 CRUD 操作为主的项目。但在复杂 SQL 场景下,仍需要结合 MyBatis 的原生能力。

### MyBatis MyBatis-Plus 的主要差异 #### 1. **核心定位** MyBatis 是一个持久层框架,专注于 SQL 手动编写映射关系管理。它提供了灵活的手写 SQL 能力以及强大的动态 SQL 支持[^1]。然而,随着业务复杂度增加,手写重复性的 CRUD 操作会显著降低开发效率。 相比之下,MyBatis-Plus (MP) 是 MyBatis 的增强工具,其设计目标是在不改变 MyBatis 核心行为的前提下提供额外的功能支持,从而减少冗余代码并提升开发效率。 --- #### 2. **内置功能扩展** ##### 自动化 CRUD MyBatis 需要手动编写 Mapper 接口及其对应的 XML 文件实现基本的增删改查操作。而在 MyBatis-Plus 中,这些基础的操作已经被封装到通用 Service 层接口 `IService` 基类 `BaseMapper` 中,无需再单独定义方法。 示例代码展示如何快速完成数据查询: ```java // 使用 BaseMapper 提供的方法直接执行查询 List<User> users = userMapper.selectList(null); ``` ##### 分页插件 分页是常见的需求之一,但在原生 MyBatis 下通常需要自行拼接 LIMIT 子句或者引入第三方库(如 PageHelper)。而 MyBatis-Plus 内置了分页插件,只需简单配置即可启用。 启动分页插件的方式如下所示: ```java @GlobalTable(pageSize = 10) public class User {} ``` --- #### 3. **性能优化特性** MyBatis-Plus 还针对一些常见场景进行了性能上的改进。例如,当批量插入大量记录时,默认情况下每条语句都会触发一次提交动作,这可能导致事务开销过高。为此,该框架新增了一个名为 BatchExecutor 的机制用于集中处理此类任务。 以下是利用批处理方式向数据库导入多条数据的例子: ```java userMapper.insertBatchSomeColumn(userList); ``` --- #### 4. **迁移注意事项** 尽管两者兼容良好,但从传统 MyBatis 切换至 MyBatis-Plus 可能遇到某些特殊情况需要注意解决办法: - 如果存在全局配置文件路径指定,则需移除相关属性以防冲突发生; - 默认开启下划线转驼峰命名规则可能影响原有逻辑运行效果,建议重新评估设置状态后再决定是否保留此项开关[^4]。 --- #### 5. **生态体系完善程度** 除了上述提到的核心能力外,围绕着 MyBatis-Plus 构建起来的一系列周边组件同样值得关注。比如专门服务于代码生成环节的产品——mybatis-plus-generator-ui ,不仅能够满足日常所需模板渲染要求,还允许用户借助可视化界面自由调整参数选项以适应不同环境下的特殊诉求[^3]。 总结来说,无论是从易用性还是功能性角度来看,选用 MyBatis-Plus 对于大多数 Java Web 应用而言都是明智之举。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值