Spring Boot + MyBatis Plus 最佳实践:从代码生成到数据库性能调优的完整指南

Max629
Max629 2026-02-10T09:02:04+08:00
0 0 0

引言

在现代Java企业级应用开发中,Spring Boot与MyBatis Plus的组合已成为主流技术栈。Spring Boot以其"约定优于配置"的理念简化了Spring应用的初始搭建和开发过程,而MyBatis Plus则通过其强大的功能扩展和便捷的操作方式,大大提升了数据库操作的效率。本文将从代码生成、数据库连接优化、SQL性能分析到缓存策略等多个维度,系统性地介绍Spring Boot + MyBatis Plus的最佳实践方案。

一、环境搭建与基础配置

1.1 项目初始化

首先,我们需要创建一个基于Spring Boot的项目。可以通过Spring Initializr快速生成项目结构:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.16</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

1.2 核心配置文件

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 2000ms

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto

二、代码自动生成工具的使用

2.1 MyBatis Plus Generator基础配置

MyBatis Plus提供了一套完整的代码生成器,可以大大减少重复性工作:

@Configuration
public class CodeGenerator {
    
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("author");
        gc.setOpen(false);
        gc.setSwagger2(true); // 实体属性 Swagger 注解
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("password");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("user");
        pc.setParent("com.example.demo");
        mpg.setPackageInfo(pc);

        // 策略配置
        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_info"); // 需要生成的表
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.execute();
    }
}

2.2 自定义代码模板

为了满足特定需求,我们可以自定义代码模板:

// 自定义模板配置
public class CustomGenerator {
    
    public static void generateWithCustomTemplate() {
        AutoGenerator mpg = new AutoGenerator();
        
        // 设置自定义模板路径
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setEntity("/templates/entity.java.vm");
        templateConfig.setMapper("/templates/mapper.java.vm");
        templateConfig.setService("/templates/service.java.vm");
        templateConfig.setServiceImpl("/templates/serviceImpl.java.vm");
        templateConfig.setController("/templates/controller.java.vm");
        mpg.setTemplate(templateConfig);
        
        // 其他配置...
        mpg.execute();
    }
}

三、数据库连接池优化

3.1 Druid连接池配置

Druid是阿里巴巴开源的数据库连接池组件,具有强大的监控和扩展能力:

# 数据源配置
spring:
  datasource:
    druid:
      # 基本属性
      url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: root
      password: password
      driver-class-name: com.mysql.cj.jdbc.Driver
      
      # 连接池配置
      initial-size: 5
      min-idle: 5
      max-active: 20
      max-wait: 60000
      time-between-eviction-runs-millis: 60000
      validation-query: SELECT 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      
      # 监控配置
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin
        allow: 127.0.0.1
        deny: 
      
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 1000
        wall:
          config:
            multi-statement-allow: true

3.2 连接池性能监控

@Component
public class ConnectionPoolMonitor {
    
    @Autowired
    private DruidDataSource dataSource;
    
    public void monitorPoolStatus() {
        // 获取连接池状态信息
        System.out.println("Active Connections: " + dataSource.getActiveCount());
        System.out.println("Idle Connections: " + dataSource.getIdleCount());
        System.out.println("Total Connections: " + dataSource.getTotal());
        
        // 监控慢SQL
        DruidStatManagerFacade statManager = DruidStatManagerFacade.getInstance();
        List<DruidStatService> services = statManager.getServices();
        for (DruidStatService service : services) {
            if (service.getSqlStat().getTotalTime() > 1000) {
                System.out.println("Slow SQL detected: " + service.getSqlStat().getSql());
            }
        }
    }
}

四、MyBatis Plus高级特性应用

4.1 条件构造器使用

@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    public List<User> queryUsers() {
        // 复杂条件查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "email")
               .eq("status", 1)
               .ge("age", 18)
               .le("age", 60)
               .like("name", "张")
               .orderByDesc("create_time");
        
        return userMapper.selectList(wrapper);
    }
    
    public Page<User> queryUsersByPage(int current, int size) {
        Page<User> page = new Page<>(current, size);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("create_time");
        
        return userMapper.selectPage(page, wrapper);
    }
}

4.2 实体类注解详解

@TableName("user_info")
public class User {
    
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    
    @TableField("user_name")
    private String userName;
    
    @TableField(exist = false)
    private String tempField; // 不参与数据库映射
    
    @Version
    private Integer version;
    
    @TableLogic
    private Integer deleted;
    
    // getter/setter...
}

五、SQL性能分析与优化

5.1 SQL执行监控配置

# 开启SQL日志输出
logging:
  level:
    com.example.demo.mapper: debug
    org.apache.ibatis: debug
    org.springframework.jdbc: debug

5.2 MyBatis Plus SQL分析器

@Configuration
public class SqlAnalysisConfig {
    
    @Bean
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor interceptor = new PerformanceInterceptor();
        interceptor.setMaxTime(1000); // SQL执行时间超过1秒记录日志
        interceptor.setFormat(true);
        return interceptor;
    }
}

5.3 慢SQL分析示例

@Service
public class SqlAnalysisService {
    
    @Autowired
    private UserMapper userMapper;
    
    public void analyzeSlowSql() {
        // 分析查询效率
        long startTime = System.currentTimeMillis();
        
        List<User> users = userMapper.selectList(null);
        
        long endTime = System.currentTimeMillis();
        System.out.println("Query time: " + (endTime - startTime) + "ms");
        
        if ((endTime - startTime) > 1000) {
            System.out.println("Potential slow query detected!");
        }
    }
}

六、缓存策略实现

6.1 Redis缓存集成

@Service
public class UserServiceWithCache {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public User getUserById(Long id) {
        String key = "user:" + id;
        
        // 先从缓存读取
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user != null) {
            return user;
        }
        
        // 缓存未命中,查询数据库
        user = userMapper.selectById(id);
        if (user != null) {
            // 写入缓存,设置过期时间30分钟
            redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
        }
        
        return user;
    }
    
    public void updateUser(User user) {
        String key = "user:" + user.getId();
        
        // 更新数据库
        userMapper.updateById(user);
        
        // 更新缓存
        redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
    }
}

6.2 缓存注解使用

@Service
public class UserServiceWithAnnotation {
    
    @Autowired
    private UserMapper userMapper;
    
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }
    
    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        userMapper.updateById(user);
        return user;
    }
    
    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }
}

七、事务管理最佳实践

7.1 事务注解配置

@Service
@Transactional(rollbackFor = Exception.class)
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private OrderItemMapper orderItemMapper;
    
    public void createOrder(Order order, List<OrderItem> items) {
        // 保存订单主表
        orderMapper.insert(order);
        
        // 保存订单明细
        for (OrderItem item : items) {
            item.setOrderId(order.getId());
            orderItemMapper.insert(item);
        }
        
        // 更新库存等操作
        updateInventory(items);
    }
    
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void updateInventory(List<OrderItem> items) {
        // 库存更新逻辑
        for (OrderItem item : items) {
            // 模拟库存扣减
            System.out.println("Updating inventory for item: " + item.getProductId());
        }
    }
}

7.2 自定义事务管理器

@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
    
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        TransactionTemplate template = new TransactionTemplate();
        template.setTransactionManager(transactionManager);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        return template;
    }
}

八、分页查询优化

8.1 MyBatis Plus分页插件配置

@Configuration
public class PaginationConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(1000L); // 设置最大分页限制
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}

8.2 分页查询实现

@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    public IPage<User> getUserPage(int current, int size) {
        Page<User> page = new Page<>(current, size);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("create_time");
        
        return userMapper.selectPage(page, wrapper);
    }
    
    public IPage<User> getAdvancedUserPage(String keyword, Integer status, int current, int size) {
        Page<User> page = new Page<>(current, size);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        if (StringUtils.hasText(keyword)) {
            wrapper.like("user_name", keyword).or().like("email", keyword);
        }
        if (status != null) {
            wrapper.eq("status", status);
        }
        wrapper.orderByDesc("create_time");
        
        return userMapper.selectPage(page, wrapper);
    }
}

九、数据安全与权限控制

9.1 敏感数据加密

@Component
public class DataEncryptionUtil {
    
    private static final String AES_KEY = "1234567890123456"; // 实际项目中应使用更安全的方式管理密钥
    
    public static String encrypt(String data) {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            byte[] encrypted = cipher.doFinal(data.getBytes());
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("Encryption failed", e);
        }
    }
    
    public static String decrypt(String encryptedData) {
        try {
            Cipher cipher = Cipher.getInstance("AES");
            SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(), "AES");
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
            return new String(decrypted);
        } catch (Exception e) {
            throw new RuntimeException("Decryption failed", e);
        }
    }
}

9.2 权限控制注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequirePermission {
    String[] value() default {};
}

// 权限检查拦截器
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
            throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            RequirePermission annotation = method.getMethodAnnotation(RequirePermission.class);
            
            if (annotation != null) {
                // 检查用户权限
                String[] permissions = annotation.value();
                if (!hasPermission(permissions)) {
                    response.setStatus(HttpStatus.FORBIDDEN.value());
                    return false;
                }
            }
        }
        return true;
    }
    
    private boolean hasPermission(String[] permissions) {
        // 实现权限检查逻辑
        return true;
    }
}

十、性能监控与调优

10.1 应用性能监控

@Component
public class PerformanceMonitor {
    
    private static final Logger logger = LoggerFactory.getLogger(PerformanceMonitor.class);
    
    public void monitorMethodExecution(String methodName, long executionTime) {
        if (executionTime > 1000) { // 超过1秒记录警告
            logger.warn("Slow method execution detected: {} took {}ms", methodName, executionTime);
        } else if (executionTime > 500) {
            logger.info("Medium execution time for {}: {}ms", methodName, executionTime);
        }
    }
    
    public void monitorDatabaseQuery(String sql, long executionTime) {
        if (executionTime > 100) { // SQL执行超过100ms记录警告
            logger.warn("Slow database query detected: {} took {}ms", sql, executionTime);
        }
    }
}

10.2 JVM性能优化建议

// JVM启动参数配置示例
/*
-Xms2g -Xmx4g 
-XX:+UseG1GC 
-XX:MaxGCPauseMillis=200 
-XX:+PrintGC 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:gc.log
*/

结语

通过本文的详细介绍,我们系统性地介绍了Spring Boot与MyBatis Plus在实际项目中的最佳实践方案。从基础环境搭建到代码自动生成,从数据库连接池优化到SQL性能分析,再到缓存策略和事务管理,每一个环节都体现了现代Java企业级应用开发的最佳实践。

在实际项目中,建议开发者根据具体业务需求选择合适的技术方案,并持续关注性能监控和优化。随着业务的发展和技术的进步,这些实践方法也需要不断迭代和完善。

记住,技术的选择应该服务于业务目标,而不是为了技术而技术。合理运用Spring Boot + MyBatis Plus的组合,能够帮助我们快速构建出高性能、可维护的企业级应用系统。

通过本文介绍的各种技术和最佳实践,相信读者能够在实际开发中更加高效地使用这些工具和技术,提升项目质量和开发效率。

相关推荐
广告位招租

相似文章

    评论 (0)

    0/2000