MyBatis Plus 核心功能与用法

目录

  • 一、 快速入门
    • 1. 创建工程与引入依赖
    • 2. 配置数据库连接
    • 3. 编写实体类
    • 4. 创建 Mapper 接口
    • 5. 测试 CRUD
  • 二、核心功能详解
    • 1. 条件构造器
      • 1. 常用 Wrapper 方法示例
      • 2. 使用示例:QueryWrapper
      • 3. 使用示例:UpdateWrapper
      • 4. 推荐使用:LambdaWrapper
    • 2. 常用注解
    • 3. 主键策略
  • 三、 Service 层封装
    • 1. 创建 Service 接口
    • 2. 创建 Service 实现类
    • 3. 使用 Service CRUD 方法
  • 四、 高级特性
    • 1. 代码生成器
    • 2. 分页查询
      • 1. 配置分页插件
      • 2. 进行分页查询
    • 3. 逻辑删除
      • 1. 数据库添加字段
      • 2. 实体类添加注解
      • 3. 配置(可选,新版 MP 可能不需要)
    • 4. 自动填充(审计)
      • 1. 实体类标记字段
      • 2. 实现 MetaObjectHandler 接口
    • 5. 乐观锁
      • 1. 数据库添加字段
      • 2. 实体类添加注解
      • 3. 配置乐观锁插件
  • 五、 总结

一、 快速入门

1. 创建工程与引入依赖

创建一个 Spring Boot 工程,并在 pom.xml 中引入 MyBatis Plus 的起步依赖。

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version> <!-- 请注意使用最新版本 -->
</dependency>

2. 配置数据库连接

在 application.yml 中配置数据库连接等信息。如果需要查看 MP 执行的 SQL 语句,可以配置日志实现。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志到控制台

3. 编写实体类

创建实体类,并使用注解与数据库表进行映射。例如,对应 user 表的 User 类:

import lombok.Data;
import com.baomidou.mybatisplus.annotation.*;

@Data // Lombok注解,自动生成getter/setter等方法
@TableName("user") // 指定关联的数据表名,如果类名与表名符合驼峰转下划线规则,可省略
public class User {
    @TableId(type = IdType.AUTO) // 指定主键及生成策略(AUTO-数据库自增)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    
    // 如果实体类字段名与数据库列名不一致,可用 @TableField 指定
    // @TableField("user_name") 
    // private String userName;
    
    // 如果实体类中存在非数据库字段,需要使用 @TableField(exist = false)
    // @TableField(exist = false)
    // private String nonDatabaseField;
}

4. 创建 Mapper 接口

创建 Mapper 接口,并使其继承 MyBatis Plus 提供的 BaseMapper 接口。继承后,无需编写 XML,即可获得大量单表 CRUD 方法。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

@Repository // 可加注解,交由Spring管理
public interface UserMapper extends BaseMapper<User> {
    // 此时无需编写任何方法,就已具备了基本的增删改查功能
}

5. 测试 CRUD

在测试类中注入 UserMapper,即可测试基本的增删改查操作。

@SpringBootTest
class MybatisPlusDemoApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testSelect() {
        // 查询所有用户
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
        
        // 根据ID查询
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }
    
    @Test
    void testInsert() {
        User newUser = new User();
        newUser.setName("张三");
        newUser.setAge(30);
        newUser.setEmail("zhangsan@example.com");
        int result = userMapper.insert(newUser); // result是受影响的行数
        System.out.println("插入成功,受影响行数:" + result);
    }
    
    // 其他CRUD操作类似,可调用 deleteById, updateById 等方法
}

二、核心功能详解

1. 条件构造器

条件构造器(Wrapper)是 MP 中用于构建复杂查询条件的强大工具,你可以用它来替代手写 WHERE 子句。

1. 常用 Wrapper 方法示例

方法名说明示例
eq等于wrapper.eq(“name”, “张三”) // name = ‘张三’
ne不等于wrapper.ne(“age”, 20) // age <> 20
gt大于wrapper.gt(“age”, 18) // age > 18
ge大于等于wrapper.ge(“age”, 20) // age >= 20
lt小于wrapper.lt(“age”, 65) // age < 65
le小于等于wrapper.le(“age”, 65) // age <= 65
between介于wrapper.between(“age”, 18, 30) // age between 18 and 30
like模糊匹配wrapper.like(“name”, “张”) // name like ‘%张%’
likeLeft左模糊匹配wrapper.likeLeft(“name”, “三”) // name like ‘%三’
likeRight右模糊匹配wrapper.likeRight(“name”, “张”) // name like ‘张%’
isNull为NULLwrapper.isNull(“email”) // email is null
isNotNull不为NULLwrapper.isNotNull(“email”) // email is not null
in包含wrapper.in(“age”, Arrays.asList(18,20,22)) // age in (18,20,22)
andAND连接wrapper.and(w -> w.eq(“name”, “李四”).gt(“age”, 25))
orOR连接wrapper.or().eq(“name”, “张三”).or().eq(“name”, “李四”)
orderByAsc升序排序wrapper.orderByAsc(“age”)
orderByDesc降序排序wrapper.orderByDesc(“create_time”)
select指定查询列wrapper.select(“id”, “name”, “email”) // 只查询特定列

2. 使用示例:QueryWrapper

@Test
void testQueryWrapper() {
    // 构建查询条件:年龄大于20且姓名中包含"张"的用户,按年龄降序
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.gt("age", 20)
           .like("name", "张")
           .orderByDesc("age");
    
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

3. 使用示例:UpdateWrapper

@Test
void testUpdateWrapper() {
    // 构建更新条件:将年龄大于25的用户的邮箱更新为特定值
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.gt("age", 25)
           .set("email", "senior@example.com"); // 直接设置值
           
    // 注意:这里传入的User实体可以为null,因为更新条件都在wrapper里
    int result = userMapper.update(null, wrapper);
    System.out.println("更新了 " + result + " 条记录");
}

4. 推荐使用:LambdaWrapper

使用 LambdaQueryWrapper 和 LambdaUpdateWrapper 可以通过方法引用来指定字段,避免硬编码字段名,从而在编译阶段就能发现错误,更加安全可靠。

@Test
void testLambdaQueryWrapper() {
    // 使用方法引用,避免拼写错误
    LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
    lambdaWrapper.gt(User::getAge, 20)
                 .like(User::getName, "张")
                 .orderByDesc(User::getAge);
                 
    List<User> users = userMapper.selectList(lambdaWrapper);
    users.forEach(System.out::println);
}

2. 常用注解

MyBatis Plus 提供了一系列注解来简化实体类与数据库表之间的映射配置。

注解作用示例
@TableName指定实体类对应的数据库表名@TableName(“sys_user”)
@TableId指定主键字段,并可设置主键策略@TableId(value = “id”, type = IdType.AUTO)
@TableField指定普通字段映射@TableField(“user_name”) @TableField(exist = false) // 非表字段
@Version用于乐观锁(后续讲解)@Version private Integer version;
@TableLogic用于逻辑删除(后续讲解)@TableLogic private Integer deleted;

3. 主键策略

@TableId 注解的 type 属性用于指定主键生成策略。

public class User {
    @TableId(value = "id", type = IdType.AUTO) // 数据库自增
    private Long id;
    // ...
}

常见的 IdType 枚举:

  • AUTO:数据库ID自增
  • ASSIGN_ID:使用雪花算法生成Long类型的ID(默认策略)
  • INPUT:用户手动输入ID

三、 Service 层封装

MyBatis Plus 不仅增强了 Mapper 层,也对 Service 层提供了强大的支持。

1. 创建 Service 接口

创建接口并继承 MP 提供的 IService 接口。

public interface UserService extends IService<User> {
    // 可以在此定义自定义方法
    // User findUserByCustomMethod(String name);
}

2. 创建 Service 实现类

创建实现类,继承 MP 提供的 ServiceImpl,并实现自定义的 Service 接口。

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 如果 UserService 接口有自定义方法,需要在这里实现
    // @Override
    // public User findUserByCustomMethod(String name) { ... }
}

3. 使用 Service CRUD 方法

在 Controller 或其他地方注入你的 Service,即可使用其内置的大量方法。

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public List<User> getAllUsers() {
        // 直接调用 IService 中提供的 list 方法
        return userService.list();
    }
    
    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable Long id) {
        // 调用 getById 方法
        return userService.getById(id);
    }
    
    // 保存、更新、删除等方法调用类似
    // userService.save(user);
    // userService.updateById(user);
    // userService.removeById(id);
}

四、 高级特性

1. 代码生成器

MyBatis Plus 内置了代码生成器(MyBatis-Plus Generator),可以根据数据库表结构自动生成 Entity、Mapper、Service、Controller 等代码,极大提升开发效率。

// 示例代码片段,具体需参考官方文档配置
FastAutoGenerator.create("jdbc:mysql://localhost:3306/your_db", "username", "password")
    .globalConfig(builder -> builder.outputDir("D://code")) // 指定输出目录
    .packageConfig(builder -> builder.parent("com.your.company")) // 指定父包名
    .strategyConfig(builder -> builder.addInclude("user", "order")) // 指定要生成的表
    .execute();

2. 分页查询

使用 MyBatis Plus 的分页功能需要先配置分页插件,然后即可使用其分页 API。

1. 配置分页插件

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

2. 进行分页查询

@Test
void testSelectPage() {
    // 创建分页对象,参数:当前页,每页大小
    Page<User> page = new Page<>(1, 5);
    // 执行分页查询,第二个参数是查询条件(Wrapper),为null则表示无条件
    userMapper.selectPage(page, null);
    
    // 从page对象获取分页数据
    System.out.println("总记录数: " + page.getTotal());
    System.out.println("当前页记录: " + page.getRecords());
    System.out.println("当前页码: " + page.getCurrent());
    System.out.println("总页数: " + page.getPages());
    System.out.println("每页大小: " + page.getSize());
    System.out.println("是否有下一页: " + page.hasNext());
    System.out.println("是否有上一页: " + page.hasPrevious());
}

3. 逻辑删除

逻辑删除并非真正物理删除数据,而是通过更新一个字段来标记数据已被删除。

1. 数据库添加字段

在表中增加一个 deleted(或自定义)字段,通常为 int 或 tinyint 类型。

2. 实体类添加注解

public class User {
    // ... 其他字段 ...
    
    @TableLogic
    // @TableField(fill = FieldFill.INSERT) // 可选,配合自动填充设置默认值
    private Integer deleted; // 0-未删除,1-已删除
}

3. 配置(可选,新版 MP 可能不需要)

在 application.yml 中配置逻辑删除的全局值(根据 MP 版本,有时可省略)。

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1 # 已删除的值
      logic-not-delete-value: 0 # 未删除的值

配置后,调用 userMapper.deleteById(id) 将会自动更新 deleted 字段为 1。查询时,MP 会自动带上 deleted = 0 的条件。

4. 自动填充(审计)

自动填充功能可用于自动处理一些通用字段的赋值,如数据的创建时间(create_time)和更新时间(update_time)。

1. 实体类标记字段

public class User {
    // ... 其他字段 ...
    
    @TableField(fill = FieldFill.INSERT) // 插入时填充
    private Date createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时填充
    private Date updateTime;
}

2. 实现 MetaObjectHandler 接口

创建一个处理器,实现插入和更新时的填充逻辑。

@Component // 记得声明为Spring组件
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        // 插入时,为 createTime 和 updateTime 设置当前时间
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时,为 updateTime 设置当前时间
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}

5. 乐观锁

乐观锁用于解决并发更新问题,通常通过一个版本号(version)字段实现。

1. 数据库添加字段

在表中增加一个 version 字段,通常为 int 类型。

2. 实体类添加注解

public class User {
    // ... 其他字段 ...
    
    @Version
    // @TableField(fill = FieldFill.INSERT) // 可选,配合自动填充设置默认值
    private Integer version;
}

3. 配置乐观锁插件

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

使用流程:

  1. 查询数据时,获取当前的 version 值(例如 version=1)。
  2. 更新数据时,将 version 作为条件:UPDATE user SET …, version = 2 WHERE id = ? AND version = 1。
  3. 如果此时该数据已被其他线程修改(即数据库中的 version 已不为 1),则本次更新返回的影响行数为 0,可根据此结果判断更新是否成功。

五、 总结

MyBatis Plus 通过丰富的功能和简洁的 API,极大地提升了基于 MyBatis 的开发效率。核心在于:

  • 简单 CRUD:通过继承 BaseMapper 和 IService,无需编写 SQL 和 XML。
  • 复杂查询:利用强大的 Wrapper,特别是 LambdaWrapper,安全地构建查询条件。
  • 高效开发:利用代码生成器、分页、逻辑删除、自动填充、乐观锁等特性,处理常见开发场景。

希望这份详解能帮助你更好地理解和使用 MyBatis Plus。如果想深入了解某个特定功能,建议查阅其官方文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木易 士心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值