MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。


一、快速入门

1. 添加依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

2. 配置

        在 application.yml 中配置:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志
  global-config:
    db-config:
      id-type: auto # 主键策略

3. 创建实体类

@Data
@TableName("user") // 指定表名
public class User {
    @TableId(type = IdType.AUTO) // 主键自增
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

4. 创建Mapper接口

public interface UserMapper extends BaseMapper<User> {
    // 继承BaseMapper即可获得CRUD功能
}

5. 使用示例

@SpringBootTest
class MpDemoApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

二、核心功能

1. CRUD 接口

        插入操作
// 插入一条记录
int insert(User entity);

// 批量插入
int insertBatchSomeColumn(List<User> entityList);
        删除操作
// 根据ID删除
int deleteById(Serializable id);

// 根据条件删除
int delete(@Param(Constants.WRAPPER) Wrapper<User> wrapper);

// 批量删除
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
        更新操作
// 根据ID更新
int updateById(@Param(Constants.ENTITY) User entity);

// 根据条件更新
int update(@Param(Constants.ENTITY) User entity, 
          @Param(Constants.WRAPPER) Wrapper<User> updateWrapper);
        查询操作
// 根据ID查询
User selectById(Serializable id);

// 查询所有
List<User> selectList(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);

// 查询一条记录
User selectOne(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);

// 查询数量
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);

2. 条件构造器

MyBatis-Plus 提供了强大的条件构造器 Wrapper,包括:

  • QueryWrapper:查询条件构造器

  • UpdateWrapper:更新条件构造器

  • LambdaQueryWrapper:Lambda语法查询构造器

  • LambdaUpdateWrapper:Lambda语法更新构造器

基本使用
// 查询年龄大于18且名字包含"张"的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
       .like("name", "张");
List<User> users = userMapper.selectList(wrapper);
Lambda方式(推荐)
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.gt(User::getAge, 18)
          .like(User::getName, "张");
List<User> users = userMapper.selectList(lambdaQuery);
常用条件方法
方法说明示例
eq等于eq("name", "张三")
ne不等于ne("name", "张三")
gt大于gt("age", 18)
ge大于等于ge("age", 18)
lt小于lt("age", 30)
le小于等于le("age", 30)
betweenBETWEENbetween("age", 18, 30)
notBetweenNOT BETWEENnotBetween("age", 18, 30)
likeLIKElike("name", "张")
notLikeNOT LIKEnotLike("name", "张")
likeLeftLIKE '%值'likeLeft("name", "三")
likeRightLIKE '值%'likeRight("name", "张")
isNullIS NULLisNull("name")
isNotNullIS NOT NULLisNotNull("name")
inINin("age", Arrays.asList(18, 20, 22))
notInNOT INnotIn("age", Arrays.asList(18, 20))
groupByGROUP BYgroupBy("dept_id")
orderByAscORDER BY ASCorderByAsc("age")
orderByDescORDER BY DESCorderByDesc("age")

3. 分页查询

        配置分页插件
@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
        使用分页
@Test
void testPage() {
    // 当前页,每页大小
    Page<User> page = new Page<>(1, 2);
    
    // 查询条件
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.gt(User::getAge, 10);
    
    // 执行查询
    Page<User> userPage = userMapper.selectPage(page, wrapper);
    
    System.out.println("总记录数:" + userPage.getTotal());
    System.out.println("当前页记录:" + userPage.getRecords());
}

4. 自定义SQL

        注解方式
public interface UserMapper extends BaseMapper<User> {
    
    @Select("SELECT * FROM user WHERE age > #{age}")
    List<User> selectByAge(@Param("age") Integer age);
}
        XML方式

                1.在 resources/mapper 下创建 UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    
    <select id="selectByName" resultType="com.example.entity.User">
        SELECT * FROM user WHERE name = #{name}
    </select>
    
</mapper>

                2.在Mapper接口中添加方法 

List<User> selectByName(@Param("name") String name);

5. 逻辑删除

        配置
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值
      logic-not-delete-value: 0 # 逻辑未删除值

                实体类添加字段 

@TableLogic
private Integer deleted;
        使用

                执行删除操作时,实际执行的是UPDATE语句:

UPDATE user SET deleted=1 WHERE id=? AND deleted=0

    三、高级功能

    1. 自动填充

    配置
    1. 实现MetaObjectHandler接口

      @Component
      public class MyMetaObjectHandler implements MetaObjectHandler {
      
          @Override
          public void insertFill(MetaObject metaObject) {
              this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
              this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
          }
      
          @Override
          public void updateFill(MetaObject metaObject) {
              this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
          }
      }
    2. 实体类添加注解

      @TableField(fill = FieldFill.INSERT)
      private LocalDateTime createTime;
      
      @TableField(fill = FieldFill.INSERT_UPDATE)
      private LocalDateTime updateTime;

    2. 乐观锁

    配置
    1. 添加插件

      @Bean
      public MybatisPlusInterceptor mybatisPlusInterceptor() {
          MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
          interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
          return interceptor;
      }
    2. 实体类添加版本字段

      @Version
      private Integer version;
      使用
      User user = userMapper.selectById(1L);
      user.setName("new name");
      userMapper.updateById(user); // 会自动带上 version 条件

    3. 枚举处理

    MyBatis-Plus 提供了完善的枚举处理方案。

    方式一:使用枚举属性
    public enum GenderEnum {
        MALE(1, "男"),
        FEMALE(2, "女");
    
        @EnumValue // 标记数据库存储的值
        private final int code;
        private final String desc;
        
        // 构造方法、getter省略
    }
     方式二:实现IEnum接口
    public enum AgeEnum implements IEnum<Integer> {
        ONE(1, "一岁"),
        TWO(2, "二岁");
        
        private int value;
        private String desc;
        
        @Override
        public Integer getValue() {
            return this.value;
        }
    }

    4. 多租户

            配置
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 多租户插件
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                // 返回当前租户ID
                return new LongValue(1L);
            }
            
            @Override
            public String getTenantIdColumn() {
                // 租户字段名
                return "tenant_id";
            }
            
            @Override
            public boolean ignoreTable(String tableName) {
                // 不需要过滤的表
                return "tenant".equals(tableName);
            }
        }));
        
        return interceptor;
    }

    5. 动态表名

            配置
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor(new TableNameHandler() {
            @Override
            public String dynamicTableName(String sql, String tableName) {
                if ("user".equals(tableName)) {
                    return "user_" + LocalDate.now().getYear();
                }
                return tableName;
            }
        }));
        
        return interceptor;
    }

    四、代码生成器

            MyBatis-Plus 提供了强大的代码生成器:

    public class CodeGenerator {
        public static void main(String[] args) {
            AutoGenerator generator = new AutoGenerator();
            
            // 全局配置
            GlobalConfig globalConfig = new GlobalConfig();
            globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
            globalConfig.setAuthor("author");
            globalConfig.setOpen(false);
            generator.setGlobalConfig(globalConfig);
            
            // 数据源配置
            DataSourceConfig dataSourceConfig = new DataSourceConfig();
            dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mp_demo");
            dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
            dataSourceConfig.setUsername("root");
            dataSourceConfig.setPassword("123456");
            generator.setDataSource(dataSourceConfig);
            
            // 包配置
            PackageConfig packageConfig = new PackageConfig();
            packageConfig.setParent("com.example");
            packageConfig.setModuleName("demo");
            generator.setPackageInfo(packageConfig);
            
            // 策略配置
            StrategyConfig strategy = new StrategyConfig();
            strategy.setNaming(NamingStrategy.underline_to_camel);
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            strategy.setEntityLombokModel(true);
            strategy.setRestControllerStyle(true);
            strategy.setInclude("user", "order"); // 要生成的表
            generator.setStrategy(strategy);
            
            generator.execute();
        }
    }

    五、最佳实践

    1. 使用Lambda表达式:避免字段名的硬编码,提高代码可读性和可维护性

    2. 合理使用分页:大数据量查询一定要使用分页

    3. 逻辑删除:优先使用逻辑删除而非物理删除

    4. 自动填充:对于创建时间、更新时间等字段使用自动填充

    5. 批量操作:大数据量操作使用批量方法提高性能

    6. 避免N+1问题:使用关联查询或自定义SQL解决

    Logo

    有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

    更多推荐