MyBatis 是经典的持久层框架,核心是手动编写 SQL 映射;而 MyBatis Plus(简称 MP)是 MyBatis 的增强工具,通过自动化 CRUD、条件构造器、代码生成器等特性简化开发。以下通过具体代码示例,从 CRUD 操作、动态 SQL、扩展功能三个维度对比两者差异。


一、环境准备

假设我们有一个 User 实体类,对应数据库表 t_user(字段:id、name、age、email)。

实体类定义

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

二、CRUD 操作对比

1. 查询单个用户(根据 ID)

MyBatis 实现

需要编写 Mapper 接口 + XML 映射文件:

  • Mapper 接口(UserMapper.java):
public interface UserMapper {
    User selectById(Long id); // 方法名与 XML 中的 SQL id 对应
}
  • XML 映射文件(UserMapper.xml):
<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectById" resultType="com.example.entity.User">
        SELECT id, name, age, email FROM t_user WHERE id = #{id}
    </select>
</mapper>

使用:

User user = userMapper.selectById(1L); // 需手动编写 XML 中的 SQL

MyBatis Plus 实现

无需编写 XML,直接继承 BaseMapper 接口,内置通用 CRUD 方法:

  • Mapper 接口(UserMapper.java):
public interface UserMapper extends BaseMapper<User> {
    // 无需额外方法,直接继承 BaseMapper 的 selectById
}

使用:

User user = userMapper.selectById(1L); // 直接调用内置方法,无需写 SQL

差异总结:MyBatis 需手动编写 XML 和 SQL;MP 内置通用方法,直接调用即可。

2. 插入用户

MyBatis 实现

  • XML 映射文件(UserMapper.xml):
<insert id="insert" parameterType="com.example.entity.User">
    INSERT INTO t_user (name, age, email) 
    VALUES (#{name}, #{age}, #{email})
</insert>

Mapper 接口:

public interface UserMapper {
    int insert(User user); // 方法名与 XML 中的 insert id 对应
}

使用:

User user = new User();
user.setName("张三");
user.setAge(20);
user.setEmail("zhangsan@example.com");
userMapper.insert(user); // 需手动写 XML 的 INSERT 语句

MyBatis Plus 实现

直接调用 BaseMapper 内置的 insert 方法:

User user = new User();
user.setName("张三");
user.setAge(20);
user.setEmail("zhangsan@example.com");
userMapper.insert(user); // 无需写 SQL,MP 自动生成 INSERT 语句

差异总结:MyBatis 需手动编写 INSERT 语句;MP 自动根据实体类字段生成 SQL。

3. 条件查询(多条件组合)

假设需要查询“年龄大于 18 岁且邮箱包含 ‘example’ 的用户”。

MyBatis 实现

通过 XML 的动态 SQL 标签(、)拼接条件:

  • XML 映射文件(UserMapper.xml):
<select id="selectByCondition" resultType="com.example.entity.User">
    SELECT * FROM t_user
    <where>
        <if test="age != null">
            AND age > #{age}
        </if>
        <if test="email != null and email != ''">
            AND email LIKE CONCAT('%', #{email}, '%')
        </if>
    </where>
</select>

Mapper 接口:

public interface UserMapper {
    List<User> selectByCondition(@Param("age") Integer age, @Param("email") String email);
}

使用:

List<User> users = userMapper.selectByCondition(18, "example"); 
// 需手动维护 XML 中的条件逻辑,字段名硬编码易出错

MyBatis Plus 实现

通过 QueryWrapper 或 LambdaQueryWrapper 链式构建条件(推荐 Lambda 避免字段名硬编码):

// 使用 LambdaQueryWrapper(推荐)
List<User> users = userMapper.selectList(
    Wrappers.<User>lambdaQuery()
        .gt(User::getAge, 18)          // 年龄 > 18
        .like(User::getEmail, "example") // 邮箱包含 "example"
);

// 等价于 MyBatis XML 中的动态 SQL 拼接,但无需手动写 XML

差异总结:

  • MyBatis 需通过 XML 动态标签拼接 SQL,字段名需与参数名严格匹配(易出错)。
  • MP 通过 Lambda 表达式链式调用,自动关联实体类字段,代码更简洁、安全。

三、动态 SQL 对比

MyBatis 的核心优势是灵活控制 SQL,适合复杂查询;MP 则通过封装简化了这一过程,但复杂场景仍可结合 MyBatis 原生能力。

1. 示例:多表联查(用户 + 订单)

假设需要查询“用户及其最近一笔订单”(用户表 t_user,订单表 t_order)。

MyBatis 实现

通过 XML 编写复杂 SQL:

<select id="selectUserWithOrder" resultMap="userOrderMap">
    SELECT u.*, o.order_no, o.amount 
    FROM t_user u
    LEFT JOIN t_order o ON u.id = o.user_id
    WHERE u.id = #{userId}
    ORDER BY o.create_time DESC
    LIMIT 1
</select>

<resultMap id="userOrderMap" type="com.example.entity.User">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <!-- 嵌套订单信息 -->
    <association property="order" column="id" select="selectOrderByUserId"/>
</resultMap>

<select id="selectOrderByUserId" resultType="com.example.entity.Order">
    SELECT order_no, amount FROM t_order WHERE user_id = #{userId} ORDER BY create_time DESC LIMIT 1
</select>

特点:需手动编写多表联查 SQL,逻辑集中在 XML 中,适合复杂场景。

MyBatis Plus 实现

MP 更适合单表操作,多表联查仍需结合 MyBatis 原生能力(或使用 MP 的 @TableField(exist = false) 扩展):

// 方式1:直接写 XML(与 MyBatis 一致)
// 方式2:使用 MP 的 LambdaQueryWrapper 结合自定义 SQL
List<User> users = userMapper.selectList(
    Wrappers.<User>lambdaQuery()
        .eq(User::getId, 1L)
        // 自定义 SQL 片段(需在 XML 中配置)
        .apply("EXISTS (SELECT 1 FROM t_order o WHERE o.user_id = t_user.id AND o.amount > 100)")
);

特点:MP 未完全封装多表联查,复杂场景仍需依赖 MyBatis 原生 XML 或自定义 SQL。


四、扩展功能对比

1. 代码生成器

MP 内置代码生成器,可自动生成实体类、Mapper、Service 等代码,大幅减少重复劳动。
配置示例(generatorConfig.java):

public class Generator {
    public static void main(String[] args) {
        AutoGenerator ag = new AutoGenerator(new DataSourceConfig.Builder("jdbc:mysql://...", "user", "pass").build());
        ag.global(GlobalConfig.builder().outputDir("D:/code").author("test").build())
            .packageInfo(PackageConfig.builder().parent("com.example").entity("entity").mapper("mapper").build())
            .strategy(StrategyConfig.builder().addInclude("t_user").build()); // 指定数据库表
        ag.execute();
    }
}

效果:运行后自动生成 User.java(实体类)、UserMapper.java(Mapper 接口)、UserMapper.xml(XML 文件)等。

2. 分页插件

MP 内置分页插件,简化物理分页实现(无需手动写 LIMIT 语句)。
配置与使用:

// 1. 配置分页插件(Spring Boot 中)
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}

// 2. 使用分页查询
Page<User> page = new Page<>(1, 10); // 第1页,每页10条
userMapper.selectPage(page, Wrappers.emptyWrapper());
List<User> list = page.getRecords(); // 当前页数据
long total = page.getTotal(); // 总记录数

MyBatis 实现分页:需手动编写 LIMIT #{start}, #{size},或使用 PageHelper 插件(非 MP 原生)。


五、核心差异总结

维度 MyBatis MyBatis Plus
CRUD 操作 需手动编写 XML 和 SQL 内置 BaseMapper,自动生成基础 CRUD
动态 SQL 通过 、 等标签灵活控制 通过 LambdaQueryWrapper 链式调用简化
多表联查 完全手动编写复杂 SQL 依赖原生 XML 或自定义 SQL
代码生成 需手动创建或使用第三方工具 内置代码生成器,自动生成实体类等
学习成本 需掌握 XML 配置、动态 SQL 等 学习成本低,适合快速上手
适用场景 复杂 SQL、高度定制化需求 单表操作为主、快速迭代项目

六、总结

  • MyBatis 是“灵活工匠”,适合需要精细控制 SQL 的复杂场景(如多表联查、存储过程)。
  • MyBatis Plus 是“高效助手”,通过自动化 CRUD、条件构造器等特性,大幅降低单表操作的开发成本,适合快速迭代的业务系统。
    实际项目中:推荐以 MP 为基础,处理 80% 的基础 CRUD;对于 20% 的复杂查询(如多表关联、高性能优化),仍使用 MyBatis 原生 XML 或自定义 SQL,兼顾效率与灵活性。
Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐