【MyBatis-Plus | 核心知识点完整指南 】

一、MyBatis-Plus 核心架构

1.1 架构层次

text

应用程序
    ↓
MyBatis-Plus (增强层)
    ├── 通用 Mapper
    ├── 条件构造器
    ├── 代码生成器
    ├── 分页插件
    ├── 性能分析插件
    └── 全局拦截插件
    ↓
MyBatis (核心层)
    ↓
JDBC
    ↓
数据库

1.2 核心特性

  • 无侵入性:只做增强不做改变

  • 强大的 CRUD:内置通用 Mapper、Service

  • Lambda 支持:类型安全的查询条件

  • 多种主键策略:雪花算法、UUID、自增等

  • 插件体系:分页、乐观锁、性能分析等

二、快速入门配置

2.1 依赖配置

xml

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

2.2 基础配置

yaml

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      id-type: assign_id
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0
  mapper-locations: classpath*:/mapper/**/*.xml

三、核心注解详解

3.1 实体类注解

java

@Data
@TableName("sys_user")  // 指定表名
public class User {
    
    @TableId(type = IdType.ASSIGN_ID)  // 主键策略
    private Long id;
    
    private String username;
    
    @TableField("nick_name")  // 字段映射
    private String nickName;
    
    @TableField(exist = false)  // 非数据库字段
    private String tempData;
    
    @TableField(fill = FieldFill.INSERT)  // 自动填充
    private LocalDateTime createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    
    @TableLogic  // 逻辑删除
    private Integer deleted;
    
    @Version  // 乐观锁
    private Integer version;
    
    @EnumValue  // 枚举值存储
    private UserStatus status;
}

3.2 主键策略详解

java

public enum IdType {
    AUTO(0),      // 数据库自增
    NONE(1),      // 无状态
    INPUT(2),     // 手动输入
    ASSIGN_ID(3), // 雪花算法(默认)
    ASSIGN_UUID(4); // UUID
    
    private final int key;
}

3.3 字段填充处理器

java

@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());
        this.strictInsertFill(metaObject, "deleted", Integer.class, 0);
    }
    
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
}

四、条件构造器深度解析

4.1 核心 Wrapper 类型

java

// 1. QueryWrapper - 普通条件构造器
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", "张三")
           .like("email", "@gmail.com")
           .between("age", 18, 30);

// 2. LambdaQueryWrapper - Lambda条件构造器(推荐)
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getUsername, "张三")
            .like(User::getEmail, "@gmail.com")
            .between(User::getAge, 18, 30);

// 3. UpdateWrapper - 更新条件构造器
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("email", "new@email.com")
            .eq("username", "张三");

// 4. LambdaUpdateWrapper - Lambda更新构造器
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(User::getEmail, "new@email.com")
                  .eq(User::getUsername, "张三");

4.2 常用条件方法

java

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

// 比较条件
wrapper.eq(User::getAge, 25)           // age = 25
       .ne(User::getAge, 25)           // age != 25
       .gt(User::getAge, 18)           // age > 18
       .ge(User::getAge, 18)           // age >= 18
       .lt(User::getAge, 60)           // age < 60
       .le(User::getAge, 60);          // age <= 60

// 范围条件
wrapper.between(User::getAge, 18, 30)  // age BETWEEN 18 AND 30
       .notBetween(User::getAge, 18, 30)
       .in(User::getAge, Arrays.asList(18, 20, 22))  // age IN (18,20,22)
       .notIn(User::getAge, Arrays.asList(18, 20, 22));

// 模糊查询
wrapper.like(User::getUsername, "张")    // username LIKE '%张%'
       .likeLeft(User::getUsername, "张") // username LIKE '%张'
       .likeRight(User::getUsername, "张") // username LIKE '张%'
       .notLike(User::getUsername, "张");

// 空值判断
wrapper.isNull(User::getEmail)         // email IS NULL
       .isNotNull(User::getEmail);     // email IS NOT NULL

// 分组排序
wrapper.groupBy(User::getDeptId)       // GROUP BY dept_id
       .orderByAsc(User::getAge)       // ORDER BY age ASC
       .orderByDesc(User::getCreateTime); // ORDER BY create_time DESC

// 链式调用
wrapper.eq(User::getStatus, 1)
       .and(w -> w.gt(User::getAge, 18).or().lt(User::getAge, 60))
       .having("count(*) > 1");

4.3 动态条件构建

java

public List<User> queryUsers(String username, Integer minAge, Integer maxAge, Integer status) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    
    // 动态条件
    wrapper.eq(StringUtils.isNotBlank(username), User::getUsername, username)
           .ge(minAge != null, User::getAge, minAge)
           .le(maxAge != null, User::getAge, maxAge)
           .eq(status != null, User::getStatus, status);
    
    return userMapper.selectList(wrapper);
}

// 复杂动态条件
public List<User> complexQuery(UserQueryDTO query) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    
    wrapper.nested(StringUtils.isNotBlank(query.getKeyword()), w -> 
            w.like(User::getUsername, query.getKeyword())
             .or()
             .like(User::getEmail, query.getKeyword()))
          .between(query.getStartTime() != null && query.getEndTime() != null, 
                  User::getCreateTime, query.getStartTime(), query.getEndTime())
          .in(query.getStatusList() != null && !query.getStatusList().isEmpty(),
                  User::getStatus, query.getStatusList());
    
    return userMapper.selectList(wrapper);
}

五、CRUD 操作详解

5.1 Mapper 层 CRUD

java

@Mapper
public interface UserMapper extends BaseMapper<User> {
    // BaseMapper 提供的核心方法:
    
    // 插入操作
    int insert(User entity);
    
    // 删除操作
    int deleteById(Serializable id);
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    int delete(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    
    // 更新操作
    int updateById(@Param(Constants.ENTITY) User entity);
    int update(@Param(Constants.ENTITY) User entity, 
               @Param(Constants.WRAPPER) Wrapper<User> updateWrapper);
    
    // 查询操作
    User selectById(Serializable id);
    List<User> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    List<User> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    User selectOne(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    List<User> selectList(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    
    // 分页查询
    <E extends IPage<User>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
}

5.2 Service 层 CRUD

java

public interface UserService extends IService<User> {
    // 自定义业务方法
    List<User> selectUsersByCondition(UserQueryDTO query);
    Page<User> selectUserPage(Page<User> page, UserQueryDTO query);
}

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> 
                             implements UserService {
    
    @Override
    public List<User> selectUsersByCondition(UserQueryDTO query) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        // 构建查询条件
        return baseMapper.selectList(wrapper);
    }
    
    @Override
    public Page<User> selectUserPage(Page<User> page, UserQueryDTO query) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        // 构建查询条件
        return baseMapper.selectPage(page, wrapper);
    }
    
    // IService 提供的核心方法:
    // boolean save(T entity);
    // boolean saveBatch(Collection<T> entityList);
    // boolean saveOrUpdate(T entity);
    // boolean removeById(Serializable id);
    // boolean removeByMap(Map<String, Object> columnMap);
    // boolean remove(Wrapper<T> queryWrapper);
    // boolean updateById(T entity);
    // boolean update(T entity, Wrapper<T> updateWrapper);
    // T getById(Serializable id);
    // List<T> listByIds(Collection<? extends Serializable> idList);
    // List<T> listByMap(Map<String, Object> columnMap);
    // T getOne(Wrapper<T> queryWrapper);
    // int count(Wrapper<T> queryWrapper);
    // List<T> list(Wrapper<T> queryWrapper);
    // Page<T> page(Page<T> page, Wrapper<T> queryWrapper);
}

5.3 批量操作优化

java

@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    // 批量插入(性能优化)
    public void batchInsertUsers(List<User> users) {
        // 方式1:使用Service的saveBatch(推荐)
        userService.saveBatch(users);
        
        // 方式2:自定义批量插入(XML方式)
        userMapper.batchInsert(users);
        
        // 方式3:循环插入(不推荐)
        for (User user : users) {
            userMapper.insert(user);
        }
    }
    
    // 批量更新
    public void batchUpdateUsers(List<User> users) {
        // 使用Service的updateBatchById
        userService.updateBatchById(users);
    }
}

六、插件系统深度解析

6.1 分页插件

java

@Configuration
public class MybatisPlusConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 分页插件
        PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInterceptor.setMaxLimit(1000L);        // 单页限制
        paginationInterceptor.setOverflow(false);        // 超出范围回到第一页
        paginationInterceptor.setOptimizeJoin(true);     // 优化联表查询
        interceptor.addInnerInterceptor(paginationInterceptor);
        
        return interceptor;
    }
}

// 分页使用
@Service
public class UserService {
    
    public PageResult<User> getUserPage(Integer pageNum, Integer pageSize, UserQueryDTO query) {
        // 创建分页对象
        Page<User> page = new Page<>(pageNum, pageSize);
        
        // 构建查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(query.getKeyword()), 
                    User::getUsername, query.getKeyword())
               .eq(query.getStatus() != null, User::getStatus, query.getStatus());
        
        // 执行分页查询
        Page<User> result = userMapper.selectPage(page, wrapper);
        
        // 返回自定义分页结果
        return new PageResult<>(
            result.getRecords(),
            result.getTotal(),
            result.getCurrent(),
            result.getSize(),
            result.getPages()
        );
    }
}

6.2 乐观锁插件

java

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

// 乐观锁使用
@Service
public class ProductService {
    
    @Transactional
    public boolean updateProductStock(Long productId, Integer quantity) {
        // 1. 查询商品
        Product product = productMapper.selectById(productId);
        
        // 2. 检查库存
        if (product.getStock() < quantity) {
            throw new BusinessException("库存不足");
        }
        
        // 3. 更新库存(自动处理版本号)
        product.setStock(product.getStock() - quantity);
        int result = productMapper.updateById(product);
        
        // 4. 处理乐观锁冲突
        if (result == 0) {
            // 重试机制或抛出异常
            throw new OptimisticLockException("数据已被其他用户修改,请重试");
        }
        
        return true;
    }
}

6.3 防止全表操作插件

java

@Configuration
public class MybatisPlusConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 防止全表更新与删除
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        
        return interceptor;
    }
}

6.4 性能分析插件

java

@Configuration
public class MybatisPlusConfig {
    
    @Bean
    @Profile({"dev", "test"})  // 只在开发测试环境使用
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 性能分析插件
        PerformanceInnerInterceptor performanceInterceptor = new PerformanceInnerInterceptor();
        performanceInterceptor.setMaxTime(1000L);  // 最大执行时间(ms)
        performanceInterceptor.setFormat(true);    // 格式化SQL
        interceptor.addInnerInterceptor(performanceInterceptor);
        
        return interceptor;
    }
}

七、高级查询技巧

7.1 查询投影

java

// 指定查询字段
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.select(User::getId, User::getUsername, User::getAge);
List<User> users = userMapper.selectList(wrapper);

// 聚合查询
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("COUNT(*) as count", 
                   "AVG(age) as avgAge", 
                   "MAX(age) as maxAge", 
                   "MIN(age) as minAge");
List<Map<String, Object>> result = userMapper.selectMaps(queryWrapper);

// 分组查询
QueryWrapper<User> groupWrapper = new QueryWrapper<>();
groupWrapper.select("dept_id", "COUNT(*) as userCount")
           .groupBy("dept_id")
           .having("userCount > 5");
List<Map<String, Object>> groupResult = userMapper.selectMaps(groupWrapper);

7.2 联表查询

java

// 方式1:使用@TableField(select = false) + 自定义XML
@Data
public class UserVO {
    private Long id;
    private String username;
    
    @TableField(select = false)
    private List<Role> roles;
}

// 在Mapper中定义联表查询方法
public interface UserMapper extends BaseMapper<User> {
    List<UserVO> selectUserWithRoles(@Param("userId") Long userId);
}

// XML配置联表查询
<!-- UserMapper.xml -->
<select id="selectUserWithRoles" resultMap="UserWithRoleResultMap">
    SELECT u.*, r.id as role_id, r.role_name
    FROM user u
    LEFT JOIN user_role ur ON u.id = ur.user_id
    LEFT JOIN role r ON ur.role_id = r.id
    WHERE u.id = #{userId}
</select>

// 方式2:使用MP-Join(第三方扩展)

7.3 子查询

java

// 使用IN子查询
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.inSql(User::getDeptId, "SELECT id FROM dept WHERE status = 1");

// 使用EXISTS子查询
wrapper.exists("SELECT 1 FROM user_role ur WHERE ur.user_id = id AND ur.role_id = 1");

// 复杂子查询
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.in("dept_id", 
    new QueryWrapper<Dept>().select("id").eq("status", 1))
    .eq("status", 1);

八、自定义SQL与XML映射

8.1 自定义Mapper方法

java

public interface UserMapper extends BaseMapper<User> {
    
    // 自定义查询方法
    List<User> selectByComplexCondition(@Param("query") UserQueryDTO query);
    
    // 自定义更新方法
    int updateStatusBatch(@Param("ids") List<Long> ids, 
                         @Param("status") Integer status);
    
    // 调用存储过程
    void callUserProcedure(@Param("userId") Long userId);
    
    // 复杂统计查询
    UserStatisticsVO selectUserStatistics();
}

8.2 XML映射配置

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="selectByComplexCondition" resultType="com.example.entity.User">
        SELECT * FROM user
        <where>
            <if test="query.username != null and query.username != ''">
                AND username LIKE CONCAT('%', #{query.username}, '%')
            </if>
            <if test="query.minAge != null">
                AND age >= #{query.minAge}
            </if>
            <if test="query.maxAge != null">
                AND age &lt;= #{query.maxAge}
            </if>
            <if test="query.statusList != null and query.statusList.size() > 0">
                AND status IN
                <foreach collection="query.statusList" item="status" 
                         open="(" separator="," close=")">
                    #{status}
                </foreach>
            </if>
        </where>
        ORDER BY create_time DESC
    </select>

    <!-- 批量更新 -->
    <update id="updateStatusBatch">
        UPDATE user SET status = #{status}, update_time = NOW()
        WHERE id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </update>

    <!-- 存储过程调用 -->
    <update id="callUserProcedure" statementType="CALLABLE">
        {call sp_update_user_status(#{userId, mode=IN})}
    </update>

</mapper>

九、多数据源支持

9.1 多数据源配置

java

@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", 
           sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
    
    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    
    @Bean
    @Primary
    public SqlSessionFactory primarySqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(primaryDataSource());
        return sessionFactory.getObject();
    }
}

@Configuration
@MapperScan(basePackages = "com.example.mapper.secondary", 
           sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
    
    @Bean
    @ConfigurationProperties("spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    
    @Bean
    public SqlSessionFactory secondarySqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(secondaryDataSource());
        return sessionFactory.getObject();
    }
}

十、代码生成器高级用法

10.1 自定义代码生成器

java

public class AdvancedCodeGenerator {
    
    public static void main(String[] args) {
        AutoGenerator generator = new AutoGenerator();
        
        // 数据源配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        generator.setDataSource(dataSource);
        
        // 全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
        globalConfig.setAuthor("YourName");
        globalConfig.setOpen(false);
        globalConfig.setSwagger2(true);  // 开启swagger注解
        globalConfig.setBaseResultMap(true);  // 生成BaseResultMap
        globalConfig.setBaseColumnList(true); // 生成BaseColumnList
        generator.setGlobalConfig(globalConfig);
        
        // 包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.example");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setController("controller");
        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", "role", "dept");  // 生成的表
        strategy.setTablePrefix("tbl_");  // 表前缀
        
        // 自定义实体类配置
        strategy.setEntityTableFieldAnnotationEnable(true);
        
        // 自定义Controller配置
        strategy.setControllerMappingHyphenStyle(true);
        
        // 自定义Service配置
        strategy.setServiceName("%sService");
        
        generator.setStrategy(strategy);
        
        // 模板配置
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setController("templates/controller.java");  // 自定义模板
        generator.setTemplate(templateConfig);
        
        // 注入配置
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                // 自定义参数
            }
        };
        generator.setCfg(injectionConfig);
        
        // 执行生成
        generator.execute();
    }
}

十一、性能优化与最佳实践

11.1 性能优化建议

java

// 1. 合理使用索引
// 为查询条件字段添加索引

// 2. 避免N+1查询
// 使用联表查询或批量查询

// 3. 分页优化
public Page<User> optimizePageQuery(Page<User> page, UserQueryDTO query) {
    // 关闭count查询(适用于不需要总条数的场景)
    page.setSearchCount(false);
    
    // 或者使用游标分页(大数据量)
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.gt(User::getId, query.getLastId())  // 基于ID的游标分页
           .last("LIMIT " + page.getSize());
    
    return userMapper.selectPage(page, wrapper);
}

// 4. 批量操作优化
@Service
public class BatchOperationService {
    
    // 使用批量插入(性能提升明显)
    public void batchInsertUsers(List<User> users) {
        userService.saveBatch(users, 1000);  // 每批1000条
    }
    
    // 使用流式查询(大数据量)
    public void processLargeData() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        try (Cursor<User> cursor = userMapper.selectCursor(wrapper)) {
            cursor.forEach(user -> {
                // 处理数据
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

11.2 最佳实践总结

  1. 实体类设计

    • 使用Lombok简化代码

    • 合理使用MP注解

    • 统一命名规范

  2. 查询优化

    • 优先使用LambdaQueryWrapper

    • 合理使用索引

    • 避免全表扫描

  3. 事务管理

    • 合理使用@Transactional

    • 注意事务传播行为

  4. 缓存策略

    • 合理使用二级缓存

    • 注意缓存一致性

  5. 监控与调优

    • 使用性能分析插件

    • 监控慢SQL

    • 定期优化数据库

十二、常见问题与解决方案

12.1 主键冲突

java

// 解决方案:统一主键策略
@TableId(type = IdType.ASSIGN_ID)  // 使用雪花算法
private Long id;

12.2 字段映射问题

java

// 解决方案:明确字段映射
@TableField("user_name")
private String userName;

@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;

12.3 乐观锁冲突

java

// 解决方案:重试机制
@Transactional
public boolean updateWithRetry(User user, int maxRetries) {
    for (int i = 0; i < maxRetries; i++) {
        try {
            User current = userMapper.selectById(user.getId());
            user.setVersion(current.getVersion());
            return userMapper.updateById(user) > 0;
        } catch (Exception e) {
            if (i == maxRetries - 1) {
                throw new BusinessException("更新失败,请重试");
            }
        }
    }
    return false;
}

12.4 分页性能问题

java

// 解决方案:游标分页
public List<User> cursorPage(Long lastId, Integer size) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    wrapper.gt(User::getId, lastId)
           .orderByAsc(User::getId)
           .last("LIMIT " + size);
    return userMapper.selectList(wrapper);
}

通过掌握这些核心知识点,你可以高效地使用 MyBatis-Plus 进行开发,充分发挥其简化开发、提升效率的优势!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值