引言
在现代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)