Spring Boot + MyBatis Plus 高效开发最佳实践:从代码生成到性能调优

DryKnight
DryKnight 2026-03-03T23:20:11+08:00
0 0 0

引言

在现代Java企业级应用开发中,Spring Boot与MyBatis Plus的组合已经成为主流的技术栈。Spring Boot以其"约定优于配置"的理念简化了Spring应用的初始搭建和开发过程,而MyBatis Plus则在MyBatis的基础上提供了更强大的功能和更便捷的使用方式。本文将深入探讨如何利用这两个框架实现高效的开发实践,从代码自动生成到性能调优,帮助开发者构建高性能、易维护的Java应用系统。

一、Spring Boot + MyBatis Plus 环境搭建与基础配置

1.1 项目依赖配置

在开始开发之前,首先需要配置正确的项目依赖。以下是一个典型的Spring Boot + MyBatis Plus项目依赖配置:

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- MyBatis Plus Starter -->
    <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.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
    
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

1.2 核心配置文件

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      # 连接池配置
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      pool-name: MyHikariCP
      
  # MyBatis Plus 配置
mybatis-plus:
  configuration:
    # 开启驼峰命名转换
    map-underscore-to-camel-case: true
    # 日志配置
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 主键策略
      id-type: auto
      # 表名前缀
      table-prefix: t_
      # 逻辑删除字段
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0
  # Mapper扫描路径
  mapper-locations: classpath*:/mapper/**/*.xml
  type-aliases-package: com.example.demo.entity

二、代码自动生成:提升开发效率的关键

2.1 MyBatis Plus 代码生成器基础使用

代码生成器是提升开发效率的重要工具,可以自动生成Entity、Mapper、Service、Controller等基础代码,减少重复劳动。

// 代码生成器配置
@Configuration
public class CodeGenerator {
    
    public static void main(String[] args) {
        // 1. 全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setAuthor("作者名");
        globalConfig.setOutputDir("D://mybatis-plus//generator");
        globalConfig.setFileOverride(true);
        globalConfig.setActiveRecord(true);
        globalConfig.setEnableCache(false);
        globalConfig.setBaseResultMap(true);
        globalConfig.setBaseColumnList(true);
        
        // 2. 数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setPassword("password");
        
        // 3. 策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setEntityLombokModel(true);
        strategyConfig.setRestControllerStyle(true);
        strategyConfig.setInclude("user", "order", "product"); // 指定生成的表名
        
        // 4. 包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.example.demo");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setController("controller");
        
        // 5. 模板配置
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setEntity("/templates/entity.java");
        templateConfig.setMapper("/templates/mapper.java");
        templateConfig.setService("/templates/service.java");
        templateConfig.setServiceImpl("/templates/serviceImpl.java");
        templateConfig.setController("/templates/controller.java");
        
        // 6. 执行生成
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(globalConfig);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setStrategy(strategyConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.setTemplate(templateConfig);
        autoGenerator.execute();
    }
}

2.2 自定义代码生成器增强

为了满足更复杂的业务需求,我们可以自定义代码生成器,添加业务逻辑处理:

public class CustomCodeGenerator {
    
    public static void generateWithCustomLogic() {
        // 配置全局信息
        GlobalConfig config = new GlobalConfig();
        config.setAuthor("开发者");
        config.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
        config.setOpen(false);
        config.setSwagger2(true);
        
        // 数据源配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDbType(DbType.MYSQL);
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        
        // 策略配置
        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", "user_role");
        
        // 自定义字段处理
        strategy.setTableFillList(Arrays.asList(
            new TableFill("create_time", FieldFill.INSERT),
            new TableFill("update_time", FieldFill.INSERT_UPDATE)
        ));
        
        // 包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.example.demo");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setController("controller");
        
        // 模板配置
        TemplateConfig template = new TemplateConfig();
        template.setEntity("/templates/entity.java.vm");
        template.setMapper("/templates/mapper.java.vm");
        template.setService("/templates/service.java.vm");
        template.setServiceImpl("/templates/serviceImpl.java.vm");
        template.setController("/templates/controller.java.vm");
        
        AutoGenerator generator = new AutoGenerator();
        generator.setGlobalConfig(config);
        generator.setDataSource(dataSource);
        generator.setStrategy(strategy);
        generator.setPackageInfo(packageConfig);
        generator.setTemplate(template);
        generator.execute();
    }
}

三、分页查询优化:处理大数据量场景

3.1 基础分页查询实现

分页查询是Web应用中的常见需求,MyBatis Plus提供了便捷的分页查询功能:

@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 基础分页查询
     */
    public IPage<User> getUserPage(int current, int size) {
        Page<User> page = new Page<>(current, size);
        return userMapper.selectPage(page, null);
    }
    
    /**
     * 带条件的分页查询
     */
    public IPage<User> getUserPageByCondition(String name, int current, int size) {
        Page<User> page = new Page<>(current, size);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.hasText(name)) {
            wrapper.like("name", name);
        }
        return userMapper.selectPage(page, wrapper);
    }
}

3.2 高性能分页查询优化

对于大数据量的分页查询,需要进行优化以避免性能问题:

@Service
public class OptimizedUserService {
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 优化的分页查询 - 使用游标分页
     */
    public PageResult<User> getUserPageWithCursor(Long lastId, int size) {
        PageResult<User> result = new PageResult<>();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        
        // 使用游标分页,避免OFFSET过大导致的性能问题
        if (lastId != null) {
            wrapper.gt("id", lastId);
        }
        wrapper.orderByAsc("id");
        wrapper.last("LIMIT " + size);
        
        List<User> users = userMapper.selectList(wrapper);
        result.setRecords(users);
        result.setHasMore(users.size() == size);
        
        return result;
    }
    
    /**
     * 带缓存的分页查询
     */
    @Cacheable(value = "userPage", key = "#current + '_' + #size + '_' + #condition")
    public IPage<User> getUserPageWithCache(String condition, int current, int size) {
        Page<User> page = new Page<>(current, size);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.hasText(condition)) {
            wrapper.like("name", condition);
        }
        return userMapper.selectPage(page, wrapper);
    }
    
    /**
     * 预估总记录数的分页查询
     */
    public PageResult<User> getUserPageWithCount(String condition, int current, int size) {
        PageResult<User> result = new PageResult<>();
        Page<User> page = new Page<>(current, size);
        
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.hasText(condition)) {
            wrapper.like("name", condition);
        }
        
        // 先查询总记录数
        Long total = userMapper.selectCount(wrapper);
        page.setTotal(total);
        
        // 查询分页数据
        List<User> records = userMapper.selectPage(page, wrapper).getRecords();
        result.setRecords(records);
        result.setTotal(total);
        result.setPages((int) Math.ceil((double) total / size));
        
        return result;
    }
}

3.3 分页查询性能监控

@Component
public class PageQueryMonitor {
    
    private static final Logger logger = LoggerFactory.getLogger(PageQueryMonitor.class);
    
    /**
     * 监控分页查询性能
     */
    public <T> IPage<T> monitorPageQuery(Supplier<IPage<T>> queryFunction, String queryName) {
        long startTime = System.currentTimeMillis();
        try {
            IPage<T> result = queryFunction.get();
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            
            if (duration > 1000) { // 超过1秒记录警告
                logger.warn("分页查询性能警告: {} 执行时间: {}ms", queryName, duration);
            } else {
                logger.info("分页查询完成: {} 执行时间: {}ms", queryName, duration);
            }
            
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            logger.error("分页查询异常: {} 执行时间: {}ms", queryName, endTime - startTime, e);
            throw e;
        }
    }
}

四、缓存策略优化:提升系统响应速度

4.1 Spring Cache 集成

@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
            .RedisCacheManagerBuilder
            .fromConnectionFactory(redisConnectionFactory())
            .withInitialCacheConfigurations(getCacheConfigurations());
        return builder.build();
    }
    
    private Map<String, RedisCacheConfiguration> getCacheConfigurations() {
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(30))
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        configMap.put("userCache", defaultConfig);
        configMap.put("productCache", defaultConfig);
        return configMap;
    }
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
            .poolConfig(getPoolConfig())
            .build();
        
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig);
    }
    
    private GenericObjectPoolConfig<?> getPoolConfig() {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);
        config.setTestOnBorrow(true);
        return config;
    }
}

4.2 缓存策略实现

@Service
public class CachedUserService {
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 基础缓存查询
     */
    @Cacheable(value = "userCache", key = "#id")
    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }
    
    /**
     * 带条件的缓存查询
     */
    @Cacheable(value = "userCache", key = "#condition")
    public List<User> getUsersByCondition(String condition) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("name", condition);
        return userMapper.selectList(wrapper);
    }
    
    /**
     * 缓存更新
     */
    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        userMapper.updateById(user);
        return user;
    }
    
    /**
     * 缓存删除
     */
    @CacheEvict(value = "userCache", key = "#id")
    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }
    
    /**
     * 批量缓存操作
     */
    @Cacheable(value = "userPageCache", key = "#current + '_' + #size")
    public IPage<User> getUserPage(int current, int size) {
        Page<User> page = new Page<>(current, size);
        return userMapper.selectPage(page, null);
    }
    
    /**
     * 缓存清除策略
     */
    @CacheEvict(value = "userCache", allEntries = true)
    public void clearUserCache() {
        // 清除所有用户缓存
    }
}

4.3 缓存穿透、击穿、雪崩防护

@Service
public class CacheProtectionService {
    
    private static final Logger logger = LoggerFactory.getLogger(CacheProtectionService.class);
    private static final String CACHE_PREFIX = "user_cache:";
    private static final String LOCK_PREFIX = "user_lock:";
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 防缓存穿透的查询
     */
    public User getUserWithProtection(Long id) {
        String cacheKey = CACHE_PREFIX + id;
        String lockKey = LOCK_PREFIX + id;
        
        // 先查缓存
        Object cached = redisTemplate.opsForValue().get(cacheKey);
        if (cached != null) {
            return (User) cached;
        }
        
        // 获取分布式锁
        if (redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 10, TimeUnit.SECONDS)) {
            try {
                // 再次检查缓存
                cached = redisTemplate.opsForValue().get(cacheKey);
                if (cached != null) {
                    return (User) cached;
                }
                
                // 查询数据库
                User user = userMapper.selectById(id);
                if (user != null) {
                    // 缓存数据
                    redisTemplate.opsForValue().set(cacheKey, user, 30, TimeUnit.MINUTES);
                } else {
                    // 缓存空值,防止缓存穿透
                    redisTemplate.opsForValue().set(cacheKey, new User(), 5, TimeUnit.MINUTES);
                }
                
                return user;
            } finally {
                // 释放锁
                redisTemplate.delete(lockKey);
            }
        } else {
            // 等待其他线程查询结果
            try {
                Thread.sleep(100);
                return getUserWithProtection(id);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return null;
            }
        }
    }
    
    /**
     * 防缓存击穿的查询
     */
    public User getUserWithTTL(Long id) {
        String cacheKey = CACHE_PREFIX + id;
        
        // 检查缓存是否即将过期
        Long ttl = redisTemplate.getExpire(cacheKey);
        if (ttl != null && ttl < 30) { // 小于30秒重新加载
            // 异步刷新缓存
            CompletableFuture.runAsync(() -> refreshCache(id));
        }
        
        Object cached = redisTemplate.opsForValue().get(cacheKey);
        if (cached != null) {
            return (User) cached;
        }
        
        return null;
    }
    
    private void refreshCache(Long id) {
        User user = userMapper.selectById(id);
        if (user != null) {
            String cacheKey = CACHE_PREFIX + id;
            redisTemplate.opsForValue().set(cacheKey, user, 30, TimeUnit.MINUTES);
        }
    }
}

五、数据库连接池配置优化

5.1 HikariCP 连接池配置

# application.yml
spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      # 连接池配置
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      pool-name: MyHikariCP
      # 连接测试配置
      validation-timeout: 5000
      connection-test-query: SELECT 1
      # 自动提交
      auto-commit: true
      # 连接属性
      data-source-properties:
        cachePrepStmts: true
        prepStmtCacheSize: 250
        prepStmtCacheSqlLimit: 2048
        useServerPrepStmts: true
        useLocalSessionState: true
        rewriteBatchedStatements: true
        cacheResultSetMetadata: true
        cacheServerConfiguration: true
        elideSetAutoCommits: true
        maintainTimeStats: false

5.2 自定义连接池配置

@Configuration
public class DataSourceConfig {
    
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        
        // 连接池配置
        dataSource.setMaximumPoolSize(20);
        dataSource.setMinimumIdle(5);
        dataSource.setConnectionTimeout(30000);
        dataSource.setIdleTimeout(600000);
        dataSource.setMaxLifetime(1800000);
        dataSource.setPoolName("MyHikariCP");
        
        // 连接测试配置
        dataSource.setValidationTimeout(5000);
        dataSource.setConnectionTestQuery("SELECT 1");
        
        // 性能优化配置
        dataSource.setLeakDetectionThreshold(60000);
        dataSource.setRegisterMbeans(true);
        
        // 连接属性优化
        Properties props = new Properties();
        props.setProperty("cachePrepStmts", "true");
        props.setProperty("prepStmtCacheSize", "250");
        props.setProperty("prepStmtCacheSqlLimit", "2048");
        props.setProperty("useServerPrepStmts", "true");
        props.setProperty("rewriteBatchedStatements", "true");
        dataSource.setDataSourceProperties(props);
        
        return dataSource;
    }
}

5.3 连接池监控与调优

@Component
public class ConnectionPoolMonitor {
    
    private static final Logger logger = LoggerFactory.getLogger(ConnectionPoolMonitor.class);
    
    @Autowired
    private HikariDataSource dataSource;
    
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void monitorConnectionPool() {
        HikariPoolMXBean poolBean = dataSource.getHikariPoolMXBean();
        
        logger.info("连接池监控信息:");
        logger.info("活跃连接数: {}", poolBean.getActiveConnections());
        logger.info("空闲连接数: {}", poolBean.getIdleConnections());
        logger.info("总连接数: {}", poolBean.getTotalConnections());
        logger.info("等待连接数: {}", poolBean.getThreadsAwaitingConnection());
        logger.info("最大连接数: {}", poolBean.getMaxConnections());
        logger.info("最小空闲连接数: {}", poolBean.getMinIdle());
        
        // 如果等待连接数过多,记录警告
        if (poolBean.getThreadsAwaitingConnection() > 5) {
            logger.warn("连接池等待连接数过多: {},可能需要增加连接池大小", 
                poolBean.getThreadsAwaitingConnection());
        }
        
        // 如果活跃连接数接近最大连接数,记录警告
        if (poolBean.getActiveConnections() > poolBean.getMaxConnections() * 0.8) {
            logger.warn("连接池活跃连接数过高: {},接近最大连接数: {}", 
                poolBean.getActiveConnections(), poolBean.getMaxConnections());
        }
    }
    
    /**
     * 动态调整连接池配置
     */
    public void adjustPoolSize(int newMaxSize) {
        try {
            HikariConfig config = dataSource.getHikariConfigMXBean();
            config.setMaximumPoolSize(newMaxSize);
            logger.info("连接池最大连接数已调整为: {}", newMaxSize);
        } catch (Exception e) {
            logger.error("调整连接池配置失败", e);
        }
    }
}

六、性能调优实战技巧

6.1 SQL 优化策略

@Service
public class OptimizedQueryService {
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 优化前的查询 - 不推荐
     */
    public List<User> getActiveUsersWithBadQuery() {
        // 这种写法会查询所有字段,即使只需要部分字段
        return userMapper.selectList(new QueryWrapper<User>().eq("status", 1));
    }
    
    /**
     * 优化后的查询 - 推荐
     */
    public List<User> getActiveUsersWithGoodQuery() {
        // 只查询需要的字段
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "email", "create_time") // 明确指定字段
               .eq("status", 1)
               .orderByDesc("create_time"); // 按时间倒序排列
        
        return userMapper.selectList(wrapper);
    }
    
    /**
     * 使用原生SQL优化复杂查询
     */
    public List<UserVO> getComplexUserQuery() {
        // 复杂查询使用原生SQL
        String sql = "SELECT u.id, u.name, u.email, u.create_time, " +
                    "(SELECT COUNT(*) FROM user_order o WHERE o.user_id = u.id) as order_count " +
                    "FROM user u WHERE u.status = 1 ORDER BY u.create_time DESC";
        
        return userMapper.selectCustomUserList(sql);
    }
    
    /**
     * 批量操作优化
     */
    public void batchInsertUsers(List<User> users) {
        // 使用批量插入优化
        userMapper.insertBatchSomeColumn(users);
    }
    
    /**
     * 分批处理大数据量
     */
    public void processLargeDataSet() {
        int pageSize = 1000;
        int offset = 0;
        boolean hasMore = true;
        
        while (hasMore) {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.last("LIMIT " + pageSize + " OFFSET " + offset);
            
            List<User> batch = userMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(batch)) {
                hasMore = false;
            } else {
                // 处理当前批次数据
                processBatch(batch);
                offset += pageSize;
            }
        }
    }
    
    private void processBatch(List<User> batch) {
        // 处理批次数据的业务逻辑
        for (User user : batch) {
            // 业务处理
        }
    }
}

6.2 索引优化策略

-- 创建合适的索引
CREATE INDEX idx_user_name ON user(name);
CREATE INDEX idx_user_email ON user(email);
CREATE INDEX idx_user_create_time ON user(create_time);
CREATE INDEX idx_user_status_time ON user(status, create_time);

-- 复合索引优化
CREATE INDEX idx_user_status_name ON user(status, name);
CREATE INDEX idx_user_status_create_time ON user(status, create_time);

6.3 事务优化

@Service
@Transactional
public class TransactionOptimizedService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private OrderMapper orderMapper;
    
    /**
     * 优化的事务处理
     */
    public void createOrderWithUser() {
        // 1. 先创建用户
        User user = new User();
        user.setName("测试用户");
相关推荐
广告位招租

相似文章

    评论 (0)

    0/2000