MyBatis-Plus核心功能与实战案例

MyBatis-Plus核心功能与实战案例,代码示例基于Spring Boot 3.x + MyBatis-Plus 3.5.3


一、MyBatis-Plus 基础篇

1. 简介与核心优势

MyBatis-Plus(MP) 是 MyBatis 的增强工具,在保留 MyBatis 原生功能的基础上,通过内置通用 Mapper、Service、条件构造器等,大幅简化开发。
核心优势

  • 无侵入:只做增强不做改变,可与 MyBatis 原生功能混合使用
  • 高效开发:内置通用 CRUD 方法,减少 80% 的重复代码
  • 强大条件构造器:支持 Lambda 表达式,避免 SQL 注入风险

2. 快速入门

环境搭建
  1. 创建 Spring Boot 项目
    • 使用 start.spring.io 生成项目,选择依赖:Spring Web, MySQL Driver, Lombok
  2. 引入 MP 依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3</version>
</dependency>
  1. 配置数据源
# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启 SQL 日志
第一个 MP 程序
  1. 定义实体类
@Data
@TableName("user") // 映射表名
public class User {
    @TableId(type = IdType.AUTO) // 主键自增
    private Long id;
    private String name;
    private Integer age;
    @TableField("email") // 字段映射
    private String email;
}
  1. 创建 Mapper 接口
public interface UserMapper extends BaseMapper<User> {}
  1. 测试 CRUD
@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
        user.setName("Jack");
        user.setAge(28);
        user.setEmail("jack@example.com");
        userMapper.insert(user); // 插入数据
    }

    @Test
    void testSelect() {
        User user = userMapper.selectById(1L); // 按 ID 查询
        System.out.println(user);
    }
}

二、核心功能实战

1. 条件构造器(Wrapper)

查询用户列表(动态条件)
public List<User> queryUsers(String name, Integer minAge) {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.like(StringUtils.isNotBlank(name), "name", name)
           .ge(minAge != null, "age", minAge)
           .orderByDesc("id");
    return userMapper.selectList(wrapper);
}

// Lambda 表达式写法(推荐)
public List<User> queryUsersLambda(String name, Integer minAge) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.like(StringUtils.isNotBlank(name), User::getName, name)
           .ge(minAge != null, User::getAge, minAge)
           .orderByDesc(User::getId);
    return userMapper.selectList(wrapper);
}
更新用户邮箱
public void updateEmail(Long userId, String newEmail) {
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("id", userId)
           .set("email", newEmail);
    userMapper.update(null, wrapper); // 参数为 null 表示不更新实体字段
}

2. 分页与排序

  1. 配置分页插件
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
  1. 分页查询订单
public Page<Order> pageOrders(int pageNum, int pageSize, String status) {
    Page<Order> page = new Page<>(pageNum, pageSize);
    LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Order::getStatus, status);
    return orderMapper.selectPage(page, wrapper);
}

3. 自动填充与逻辑删除

自动填充创建时间
  1. 实体类配置
public class User {
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
}
  1. 实现 MetaObjectHandler
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
    }
}
逻辑删除配置
  1. 实体类标记
@TableLogic
private Integer deleted; // 0-未删除,1-已删除
  1. 全局配置
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted  # 逻辑删除字段
      logic-delete-value: 1        # 删除值
      logic-not-delete-value: 0    # 未删除值

三、高级特性与扩展

1. 多数据源配置(以两个数据源为例)

  1. 引入依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>
  1. 配置数据源
spring:
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/db1
          username: root
          password: 123456
        slave:
          url: jdbc:mysql://localhost:3306/db2
          username: root
          password: 123456
  1. 使用注解切换数据源
@DS("slave") // 指定从库
public List<User> getSlaveUsers() {
    return userMapper.selectList(null);
}

2. 自定义 SQL 注入器(扩展全局方法)

  1. 定义自定义方法
public class DeleteAllMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "delete from " + tableInfo.getTableName();
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addDeleteMappedStatement(mapperClass, "deleteAll", sqlSource);
    }
}
  1. 注册注入器
@Component
public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methods = super.getMethodList(mapperClass);
        methods.add(new DeleteAllMethod());
        return methods;
    }
}
  1. Mapper 接口调用
public interface UserMapper extends BaseMapper<User> {
    void deleteAll();
}

四、最佳实践与常见问题

1. 最佳实践

  • 实体类规范
    • 使用 @TableName 明确表名,避免默认转换(如 user_infouserInfo
    • 避免在实体类中使用数据库关键字(如 order → 改用 orderNo
  • 事务控制:在 Service 层添加 @Transactional
@Transactional(rollbackFor = Exception.class)
public void updateUserAndLog(User user, String logContent) {
    userMapper.updateById(user);
    logMapper.insert(new Log(logContent));
}

2. 常见问题排查

  • 字段映射失败
    • 检查 @TableField 注解的 value 是否与数据库字段名一致
    • 查看 SQL 日志确认生成的 SQL 语句
  • 分页失效
    • 确保配置了 PaginationInnerInterceptor
    • 检查 Page 对象是否作为第一个参数传入

五、综合实战项目:博客系统

1. 数据库设计

CREATE TABLE `article` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
  `title` VARCHAR(100) NOT NULL,
  `content` TEXT,
  `author_id` BIGINT NOT NULL,
  `create_time` DATETIME
);

CREATE TABLE `comment` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
  `article_id` BIGINT NOT NULL,
  `content` VARCHAR(500),
  `user_id` BIGINT NOT NULL
);

2. 代码生成器配置

FastAutoGenerator.create("jdbc:mysql://localhost:3306/blog", "root", "123456")
    .globalConfig(builder -> builder.author("YourName").outputDir("src/main/java"))
    .packageConfig(builder -> builder.parent("com.example.blog"))
    .strategyConfig(builder -> builder.addInclude("article", "comment"))
    .execute();

3. 核心功能实现

文章分页查询

public Page<Article> pageArticles(int pageNum, int pageSize, String keyword) {
    Page<Article> page = new Page<>(pageNum, pageSize);
    LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
    wrapper.like(StringUtils.isNotBlank(keyword), Article::getTitle, keyword);
    return articleMapper.selectPage(page, wrapper);
}

评论事务处理

@Transactional
public void addComment(Comment comment) {
    commentMapper.insert(comment);
    // 更新文章评论数
    articleMapper.update(null, 
        new UpdateWrapper<Article>()
            .eq("id", comment.getArticleId())
            .setSql("comment_count = comment_count + 1"));
}

通过以上内容,开发者可系统掌握 MyBatis-Plus 的核心功能,并具备企业级项目开发能力。建议结合官方文档与实战项目深化理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值