@llryiop/avatar-boot-cli 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/docs/exam-question-generate-api.md +163 -0
  2. package/package.json +1 -1
  3. package/src/prompts.js +3 -3
  4. package/src/transform.js +1 -1
  5. package/templates/.claude/skills/avatar-boot-starter-feign/README.md +243 -0
  6. package/templates/.claude/skills/avatar-boot-starter-feign/SKILL.md +47 -219
  7. package/templates/.claude/skills/avatar-boot-starter-feign/references//345/212/237/350/203/275/350/257/246/350/247/243.md +65 -0
  8. package/templates/.claude/skills/avatar-boot-starter-feign/references//345/277/253/351/200/237/346/216/245/345/205/245/346/214/207/345/215/227.md +75 -0
  9. package/templates/.claude/skills/avatar-boot-starter-feign/references//351/205/215/347/275/256/345/217/202/350/200/203.md +70 -0
  10. package/templates/.claude/skills/avatar-boot-starter-job/README.md +437 -0
  11. package/templates/.claude/skills/avatar-boot-starter-job/SKILL.md +35 -414
  12. package/templates/.claude/skills/avatar-boot-starter-job/references//345/270/270/350/247/201/351/227/256/351/242/230.md +55 -0
  13. package/templates/.claude/skills/avatar-boot-starter-job/references//345/277/253/351/200/237/346/216/245/345/205/245/344/270/216/351/205/215/347/275/256.md +124 -0
  14. package/templates/.claude/skills/avatar-boot-starter-job/references//347/233/221/346/216/247/346/214/207/346/240/207.md +72 -0
  15. package/templates/.claude/skills/avatar-boot-starter-kafka/README.md +580 -0
  16. package/templates/.claude/skills/avatar-boot-starter-kafka/SKILL.md +36 -560
  17. package/templates/.claude/skills/avatar-boot-starter-kafka/references//346/234/200/344/275/263/345/256/236/350/267/265.md +43 -0
  18. package/templates/.claude/skills/avatar-boot-starter-kafka/references//346/240/270/345/277/203/345/212/237/350/203/275.md +117 -0
  19. package/templates/.claude/skills/avatar-boot-starter-kafka/references//351/205/215/347/275/256/345/217/202/350/200/203.md +54 -0
  20. package/templates/.claude/skills/avatar-boot-starter-mysql/README.md +572 -0
  21. package/templates/.claude/skills/avatar-boot-starter-mysql/SKILL.md +40 -550
  22. package/templates/.claude/skills/avatar-boot-starter-mysql/references//345/256/236/344/275/223/344/270/216/345/212/237/350/203/275.md +96 -0
  23. package/templates/.claude/skills/avatar-boot-starter-mysql/references//345/277/253/351/200/237/346/216/245/345/205/245/344/270/216/346/225/260/346/215/256/346/272/220.md +91 -0
  24. package/templates/.claude/skills/avatar-boot-starter-mysql/references//351/253/230/347/272/247/347/211/271/346/200/247/344/270/216/351/205/215/347/275/256.md +59 -0
  25. package/templates/.claude/skills/avatar-boot-starter-nacos/README.md +901 -0
  26. package/templates/.claude/skills/avatar-boot-starter-nacos/SKILL.md +40 -879
  27. package/templates/.claude/skills/avatar-boot-starter-nacos/references//345/212/237/350/203/275/344/275/277/347/224/250.md +134 -0
  28. package/templates/.claude/skills/avatar-boot-starter-nacos/references//345/277/253/351/200/237/346/216/245/345/205/245/344/270/216/351/205/215/347/275/256.md +96 -0
  29. package/templates/.claude/skills/avatar-boot-starter-nacos/references//346/225/205/351/232/234/346/216/222/346/237/245.md +64 -0
  30. package/templates/.claude/skills/avatar-boot-starter-oss/README.md +594 -0
  31. package/templates/.claude/skills/avatar-boot-starter-oss/SKILL.md +52 -570
  32. package/templates/.claude/skills/avatar-boot-starter-oss/references//345/277/253/351/200/237/346/216/245/345/205/245/344/270/216/351/205/215/347/275/256.md +77 -0
  33. package/templates/.claude/skills/avatar-boot-starter-oss/references//346/240/270/345/277/203/345/212/237/350/203/275.md +94 -0
  34. package/templates/.claude/skills/avatar-boot-starter-oss/references//350/247/204/350/214/203/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.md +61 -0
  35. package/templates/.claude/skills/avatar-boot-starter-redis/README.md +586 -0
  36. package/templates/.claude/skills/avatar-boot-starter-redis/SKILL.md +42 -566
  37. package/templates/.claude/skills/avatar-boot-starter-redis/references//345/277/253/351/200/237/346/216/245/345/205/245/344/270/216/351/205/215/347/275/256.md +78 -0
  38. package/templates/.claude/skills/avatar-boot-starter-redis/references//346/225/260/346/215/256/346/223/215/344/275/234.md +111 -0
  39. package/templates/.claude/skills/avatar-boot-starter-redis/references//351/253/230/347/272/247/345/212/237/350/203/275.md +90 -0
  40. package/templates/.claude/skills/avatar-boot-starter-rocketmq/README.md +662 -0
  41. package/templates/.claude/skills/avatar-boot-starter-rocketmq/SKILL.md +48 -640
  42. package/templates/.claude/skills/avatar-boot-starter-rocketmq/references//346/240/270/345/277/203/345/212/237/350/203/275.md +101 -0
  43. package/templates/.claude/skills/avatar-boot-starter-rocketmq/references//351/205/215/347/275/256/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.md +44 -0
  44. package/templates/.claude/skills/avatar-boot-starter-rocketmq/references//351/253/230/347/272/247/347/211/271/346/200/247.md +71 -0
  45. package/templates/.claude/skills/avatar-boot-starter-web/README.md +1007 -0
  46. package/templates/.claude/skills/avatar-boot-starter-web/SKILL.md +150 -1003
  47. package/templates/.claude/skills/avatar-boot-starter-web/references//345/212/237/350/203/275-LogInfo/346/263/250/350/247/243.md +75 -0
  48. package/templates/.claude/skills/avatar-boot-starter-web/references//345/212/237/350/203/275-/345/205/250/345/261/200/345/274/202/345/270/270/345/244/204/347/220/206.md +90 -0
  49. package/templates/.claude/skills/avatar-boot-starter-web/references//345/212/237/350/203/275-/346/214/207/346/240/207/347/233/221/346/216/247.md +74 -0
  50. package/templates/.claude/skills/avatar-boot-starter-web/references//345/212/237/350/203/275-/346/227/245/345/277/227/344/275/223/347/263/273.md +73 -0
  51. package/templates/.claude/skills/avatar-boot-starter-web/references//345/212/237/350/203/275-/350/257/267/346/261/202/344/270/212/344/270/213/346/226/207.md +77 -0
  52. package/templates/.claude/skills/avatar-boot-starter-web/references//345/277/253/351/200/237/346/216/245/345/205/245/346/214/207/345/215/227.md +52 -0
  53. package/templates/.claude/skills/avatar-boot-starter-web/references//346/263/250/346/204/217/344/272/213/351/241/271.md +68 -0
  54. package/templates/.claude/skills/avatar-boot-starter-web/references//350/207/252/345/256/232/344/271/211/346/211/251/345/261/225/346/214/207/345/215/227.md +107 -0
  55. package/templates/.claude/skills/avatar-boot-starter-web/references//351/205/215/347/275/256/345/217/202/350/200/203.md +107 -0
  56. package/templates/.claude/skills/crud-generator/SKILL.md +133 -64
  57. package/templates/.claude/skills/database-design/README.md +207 -0
  58. package/templates/.claude/skills/database-design/SKILL.md +469 -82
  59. package/templates/.claude/skills/database-design/references//345/221/275/345/220/215/350/247/204/350/214/203.md +232 -0
  60. package/templates/.claude/skills/database-design/references//345/255/227/346/256/265/347/261/273/345/236/213/350/247/204/350/214/203.md +400 -0
  61. package/templates/.claude/skills/database-design/references//347/264/242/345/274/225/350/247/204/350/214/203.md +506 -0
  62. package/templates/avatar-scaffold-api/pom.xml +0 -5
  63. package/templates/avatar-scaffold-service/pom.xml +25 -87
  64. package/templates/avatar-scaffold-service/src/main/resources/application-dev.yaml +3 -5
  65. package/templates/avatar-scaffold-service/src/main/resources/application-local.yaml +2 -2
  66. package/templates/pom.xml +9 -18
@@ -0,0 +1,572 @@
1
+ ---
2
+ name: avatar-boot-starter-mysql
3
+ description: 当涉及 MySQL、数据库、Druid、数据源、MyBatis Plus、SQL 相关功能时使用此技能 - 为 Spring Boot 3.5.3 应用提供基于 Druid 1.2.24 连接池和 MyBatis Plus 3.5.15 的数据库访问能力,包含自动配置、SQL 监控、多数据源支持。
4
+ ---
5
+
6
+ Avatar Boot 的 MySQL 数据库集成模块,基于 Druid 1.2.24 连接池和 MyBatis Plus 3.5.15 提供开箱即用的数据库访问能力。
7
+
8
+ ## 功能特性
9
+
10
+ - ✅ **Druid 连接池** - 内置 Druid 1.2.24,提供高性能连接池管理和 SQL 监控
11
+ - ✅ **MyBatis Plus 集成** - 基于 mybatis-plus-spring-boot3-starter 3.5.15,提供增强 CRUD 能力
12
+ - ✅ **SQL 监控** - Druid 内置 SQL 监控面板,实时查看慢 SQL 和连接池状态
13
+ - ✅ **自动分页** - 内置分页插件,支持多种数据库方言
14
+ - ✅ **代码生成** - 支持 MyBatis Plus 代码生成器,快速生成 Entity/Mapper/Service
15
+ - ✅ **多数据源** - 支持多数据源配置和动态切换
16
+
17
+ ## 快速开始
18
+
19
+ ### 1. 添加依赖
20
+
21
+ 在项目的 `pom.xml` 中添加依赖:
22
+
23
+ ```xml
24
+ <dependency>
25
+ <groupId>com.iflytek.avatar.boot</groupId>
26
+ <artifactId>avatar-boot-starter-mysql</artifactId>
27
+ </dependency>
28
+ ```
29
+
30
+ > 版本由 Avatar Boot BOM 统一管理,无需指定 version。
31
+
32
+ ### 2. 配置文件
33
+
34
+ 在 `application.yml` 中配置数据源:
35
+
36
+ ```yaml
37
+ spring:
38
+ datasource:
39
+ type: com.alibaba.druid.pool.DruidDataSource
40
+ driver-class-name: com.mysql.cj.jdbc.Driver
41
+ url: jdbc:mysql://localhost:3306/your_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
42
+ username: root
43
+ password: your-password
44
+ druid:
45
+ # 连接池配置
46
+ initial-size: 5 # 初始化连接数
47
+ min-idle: 5 # 最小空闲连接数
48
+ max-active: 20 # 最大活跃连接数
49
+ max-wait: 60000 # 获取连接最大等待时间(毫秒)
50
+ # 连接检测
51
+ validation-query: SELECT 1
52
+ test-while-idle: true
53
+ test-on-borrow: false
54
+ test-on-return: false
55
+ time-between-eviction-runs-millis: 60000 # 检测间隔
56
+ min-evictable-idle-time-millis: 300000 # 最小空闲时间
57
+ # 监控统计
58
+ filters: stat,wall,slf4j # 启用统计、防火墙、日志过滤器
59
+ stat-view-servlet:
60
+ enabled: true
61
+ url-pattern: /druid/*
62
+ login-username: admin
63
+ login-password: admin123
64
+ allow: ""
65
+ web-stat-filter:
66
+ enabled: true
67
+ url-pattern: /*
68
+ exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
69
+ filter:
70
+ stat:
71
+ slow-sql-millis: 2000 # 慢 SQL 阈值(毫秒)
72
+ log-slow-sql: true # 记录慢 SQL
73
+ merge-sql: true # 合并 SQL 统计
74
+ wall:
75
+ config:
76
+ multi-statement-allow: false # 禁止多语句执行
77
+ delete-allow: true
78
+ ```
79
+
80
+ ### 3. MyBatis Plus 配置
81
+
82
+ ```yaml
83
+ mybatis-plus:
84
+ mapper-locations: classpath*:mapper/**/*.xml # Mapper XML 文件位置
85
+ type-aliases-package: com.example.entity # 实体类包路径
86
+ configuration:
87
+ map-underscore-to-camel-case: true # 驼峰命名映射
88
+ log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl # SQL 日志
89
+ global-config:
90
+ db-config:
91
+ id-type: assign_id # 主键策略:雪花算法
92
+ logic-delete-field: deleted # 逻辑删除字段
93
+ logic-delete-value: 1 # 已删除值
94
+ logic-not-delete-value: 0 # 未删除值
95
+ table-prefix: t_ # 表名前缀(可选)
96
+ ```
97
+
98
+ ## Entity / Mapper / Service 模式
99
+
100
+ ### Entity 实体类
101
+
102
+ ```java
103
+ package com.example.entity;
104
+
105
+ import com.baomidou.mybatisplus.annotation.*;
106
+ import lombok.Data;
107
+
108
+ import java.io.Serial;
109
+ import java.io.Serializable;
110
+ import java.time.LocalDateTime;
111
+
112
+ @Data
113
+ @TableName("t_user")
114
+ public class User implements Serializable {
115
+
116
+ @Serial
117
+ private static final long serialVersionUID = 1L;
118
+
119
+ /**
120
+ * 主键(雪花算法)
121
+ */
122
+ @TableId(type = IdType.ASSIGN_ID)
123
+ private Long id;
124
+
125
+ /**
126
+ * 用户名
127
+ */
128
+ private String username;
129
+
130
+ /**
131
+ * 邮箱
132
+ */
133
+ private String email;
134
+
135
+ /**
136
+ * 状态:0-禁用,1-启用
137
+ */
138
+ private Integer status;
139
+
140
+ /**
141
+ * 创建时间(自动填充)
142
+ */
143
+ @TableField(fill = FieldFill.INSERT)
144
+ private LocalDateTime createTime;
145
+
146
+ /**
147
+ * 更新时间(自动填充)
148
+ */
149
+ @TableField(fill = FieldFill.INSERT_UPDATE)
150
+ private LocalDateTime updateTime;
151
+
152
+ /**
153
+ * 逻辑删除标识
154
+ */
155
+ @TableLogic
156
+ private Integer deleted;
157
+ }
158
+ ```
159
+
160
+ ### Mapper 接口
161
+
162
+ ```java
163
+ package com.example.mapper;
164
+
165
+ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
166
+ import com.example.entity.User;
167
+ import org.apache.ibatis.annotations.Mapper;
168
+ import org.apache.ibatis.annotations.Param;
169
+ import org.apache.ibatis.annotations.Select;
170
+
171
+ import java.util.List;
172
+
173
+ @Mapper
174
+ public interface UserMapper extends BaseMapper<User> {
175
+
176
+ /**
177
+ * 自定义查询(注解方式)
178
+ */
179
+ @Select("SELECT * FROM t_user WHERE status = #{status}")
180
+ List<User> selectByStatus(@Param("status") Integer status);
181
+ }
182
+ ```
183
+
184
+ ### Service 接口与实现
185
+
186
+ ```java
187
+ package com.example.service;
188
+
189
+ import com.baomidou.mybatisplus.extension.service.IService;
190
+ import com.example.entity.User;
191
+
192
+ public interface UserService extends IService<User> {
193
+ /**
194
+ * 根据用户名查询
195
+ */
196
+ User getByUsername(String username);
197
+ }
198
+ ```
199
+
200
+ ```java
201
+ package com.example.service.impl;
202
+
203
+ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
204
+ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
205
+ import com.example.entity.User;
206
+ import com.example.mapper.UserMapper;
207
+ import com.example.service.UserService;
208
+ import org.springframework.stereotype.Service;
209
+
210
+ @Service
211
+ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
212
+
213
+ @Override
214
+ public User getByUsername(String username) {
215
+ return this.getOne(new LambdaQueryWrapper<User>()
216
+ .eq(User::getUsername, username));
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### 分页查询
222
+
223
+ ```java
224
+ package com.example.config;
225
+
226
+ import com.baomidou.mybatisplus.annotation.DbType;
227
+ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
228
+ import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
229
+ import org.springframework.context.annotation.Bean;
230
+ import org.springframework.context.annotation.Configuration;
231
+
232
+ @Configuration
233
+ public class MybatisPlusConfig {
234
+
235
+ @Bean
236
+ public MybatisPlusInterceptor mybatisPlusInterceptor() {
237
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
238
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
239
+ return interceptor;
240
+ }
241
+ }
242
+ ```
243
+
244
+ ```java
245
+ @Service
246
+ @RequiredArgsConstructor
247
+ public class UserQueryService {
248
+
249
+ private final UserService userService;
250
+
251
+ /**
252
+ * 分页查询用户
253
+ */
254
+ public IPage<User> pageQuery(int current, int size, String username) {
255
+ Page<User> page = new Page<>(current, size);
256
+ LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
257
+ .like(StringUtils.isNotBlank(username), User::getUsername, username)
258
+ .eq(User::getDeleted, 0)
259
+ .orderByDesc(User::getCreateTime);
260
+ return userService.page(page, wrapper);
261
+ }
262
+ }
263
+ ```
264
+
265
+ ## Druid 监控面板
266
+
267
+ 启动应用后,访问 `http://localhost:8080/druid/` 即可查看 Druid 监控面板。
268
+
269
+ ### 监控内容
270
+
271
+ | 面板 | 功能 |
272
+ |------|------|
273
+ | 数据源 | 连接池状态、活跃连接数、等待线程数 |
274
+ | SQL 监控 | SQL 执行次数、耗时统计、慢 SQL 列表 |
275
+ | SQL 防火墙 | 拦截的危险 SQL 统计 |
276
+ | Web 应用 | 请求 URI 统计、关联 SQL |
277
+ | Spring 监控 | Spring Bean 方法调用统计 |
278
+
279
+ ### 安全配置
280
+
281
+ 生产环境建议限制访问:
282
+
283
+ ```yaml
284
+ spring:
285
+ datasource:
286
+ druid:
287
+ stat-view-servlet:
288
+ enabled: true
289
+ allow: 10.0.0.0/8 # 仅内网访问
290
+ deny: ""
291
+ login-username: ${DRUID_USERNAME}
292
+ login-password: ${DRUID_PASSWORD}
293
+ ```
294
+
295
+ ## 事务管理
296
+
297
+ ### @Transactional 使用规范
298
+
299
+ ```java
300
+ @Service
301
+ @RequiredArgsConstructor
302
+ public class OrderService {
303
+
304
+ private final OrderMapper orderMapper;
305
+ private final OrderItemMapper orderItemMapper;
306
+
307
+ /**
308
+ * 创建订单(事务)
309
+ * 注意:@Transactional 默认只回滚 RuntimeException
310
+ */
311
+ @Transactional(rollbackFor = Exception.class)
312
+ public Long createOrder(OrderDTO dto) {
313
+ // 1. 创建主订单
314
+ Order order = new Order();
315
+ order.setOrderNo(generateOrderNo());
316
+ order.setTotalAmount(dto.getTotalAmount());
317
+ orderMapper.insert(order);
318
+
319
+ // 2. 创建订单明细
320
+ for (OrderItemDTO item : dto.getItems()) {
321
+ OrderItem orderItem = new OrderItem();
322
+ orderItem.setOrderId(order.getId());
323
+ orderItem.setProductId(item.getProductId());
324
+ orderItem.setQuantity(item.getQuantity());
325
+ orderItemMapper.insert(orderItem);
326
+ }
327
+
328
+ return order.getId();
329
+ }
330
+ }
331
+ ```
332
+
333
+ ### 事务最佳实践
334
+
335
+ 1. **必须指定 `rollbackFor = Exception.class`**:默认只回滚 RuntimeException
336
+ 2. **避免在事务方法中调用同类方法**:Spring AOP 代理限制,同类内部调用不生效
337
+ 3. **事务方法必须是 public**:非 public 方法事务不生效
338
+ 4. **控制事务粒度**:不要在大方法上加 @Transactional,只在需要事务的方法上使用
339
+ 5. **避免事务中做耗时操作**:如 HTTP 调用、文件上传,会长时间占用数据库连接
340
+
341
+ ```java
342
+ // 错误示例:事务中调用远程服务
343
+ @Transactional(rollbackFor = Exception.class)
344
+ public void badExample() {
345
+ orderMapper.insert(order);
346
+ // 不要在事务中做远程调用!
347
+ httpClient.callRemoteService(); // 如果超时,数据库连接被长时间占用
348
+ }
349
+
350
+ // 正确示例:将远程调用移出事务
351
+ public void goodExample() {
352
+ createOrderInTransaction(order);
353
+ httpClient.callRemoteService(); // 事务外调用
354
+ }
355
+
356
+ @Transactional(rollbackFor = Exception.class)
357
+ public void createOrderInTransaction(Order order) {
358
+ orderMapper.insert(order);
359
+ }
360
+ ```
361
+
362
+ ## 多数据源配置
363
+
364
+ ### 配置文件
365
+
366
+ ```yaml
367
+ spring:
368
+ datasource:
369
+ primary:
370
+ type: com.alibaba.druid.pool.DruidDataSource
371
+ driver-class-name: com.mysql.cj.jdbc.Driver
372
+ url: jdbc:mysql://localhost:3306/primary_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
373
+ username: root
374
+ password: password1
375
+ druid:
376
+ initial-size: 5
377
+ max-active: 20
378
+ secondary:
379
+ type: com.alibaba.druid.pool.DruidDataSource
380
+ driver-class-name: com.mysql.cj.jdbc.Driver
381
+ url: jdbc:mysql://localhost:3306/secondary_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
382
+ username: root
383
+ password: password2
384
+ druid:
385
+ initial-size: 5
386
+ max-active: 20
387
+ ```
388
+
389
+ ### 数据源配置类
390
+
391
+ ```java
392
+ package com.example.config;
393
+
394
+ import com.alibaba.druid.pool.DruidDataSource;
395
+ import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
396
+ import org.apache.ibatis.session.SqlSessionFactory;
397
+ import org.mybatis.spring.annotation.MapperScan;
398
+ import org.springframework.boot.context.properties.ConfigurationProperties;
399
+ import org.springframework.context.annotation.Bean;
400
+ import org.springframework.context.annotation.Configuration;
401
+ import org.springframework.context.annotation.Primary;
402
+ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
403
+
404
+ import javax.sql.DataSource;
405
+
406
+ @Configuration
407
+ @MapperScan(basePackages = "com.example.mapper.primary",
408
+ sqlSessionFactoryRef = "primarySqlSessionFactory")
409
+ public class PrimaryDataSourceConfig {
410
+
411
+ @Primary
412
+ @Bean("primaryDataSource")
413
+ @ConfigurationProperties(prefix = "spring.datasource.primary")
414
+ public DataSource primaryDataSource() {
415
+ return new DruidDataSource();
416
+ }
417
+
418
+ @Primary
419
+ @Bean("primarySqlSessionFactory")
420
+ public SqlSessionFactory primarySqlSessionFactory(DataSource primaryDataSource) throws Exception {
421
+ MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
422
+ factory.setDataSource(primaryDataSource);
423
+ factory.setMapperLocations(
424
+ new PathMatchingResourcePatternResolver()
425
+ .getResources("classpath:mapper/primary/**/*.xml"));
426
+ return factory.getObject();
427
+ }
428
+ }
429
+ ```
430
+
431
+ ## 自动填充配置
432
+
433
+ ```java
434
+ package com.example.config;
435
+
436
+ import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
437
+ import lombok.extern.slf4j.Slf4j;
438
+ import org.apache.ibatis.reflection.MetaObject;
439
+ import org.springframework.stereotype.Component;
440
+
441
+ import java.time.LocalDateTime;
442
+
443
+ @Slf4j
444
+ @Component
445
+ public class MyMetaObjectHandler implements MetaObjectHandler {
446
+
447
+ @Override
448
+ public void insertFill(MetaObject metaObject) {
449
+ this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
450
+ this.strictInsertFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
451
+ }
452
+
453
+ @Override
454
+ public void updateFill(MetaObject metaObject) {
455
+ this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
456
+ }
457
+ }
458
+ ```
459
+
460
+ ## 慢 SQL 排查
461
+
462
+ ### 1. Druid 慢 SQL 监控
463
+
464
+ 通过 Druid 监控面板查看:
465
+ - 访问 `/druid/sql.html` 查看所有 SQL 统计
466
+ - 按执行时间排序,找到慢 SQL
467
+ - 查看 SQL 执行计划和参数
468
+
469
+ ### 2. MySQL EXPLAIN 分析
470
+
471
+ ```sql
472
+ -- 分析查询执行计划
473
+ EXPLAIN SELECT * FROM t_user WHERE username = 'zhangsan';
474
+
475
+ -- 关注以下字段:
476
+ -- type: ALL(全表扫描,需优化)、index、range、ref、const
477
+ -- rows: 扫描行数
478
+ -- Extra: Using filesort(需优化)、Using temporary(需优化)
479
+ ```
480
+
481
+ ### 3. 索引优化建议
482
+
483
+ - 为 WHERE 条件的字段添加索引
484
+ - 避免在索引列上使用函数或计算
485
+ - 联合索引遵循最左前缀原则
486
+ - 使用覆盖索引减少回表查询
487
+
488
+ ## 最佳实践
489
+
490
+ ### 1. 连接池配置
491
+
492
+ - **initial-size 和 min-idle 相同**:避免连接池频繁创建/销毁连接
493
+ - **max-active 合理设置**:建议 20-50,根据服务器配置和并发量调整
494
+ - **启用 test-while-idle**:定期检测空闲连接有效性
495
+ - **设置 max-wait**:避免无限等待连接
496
+
497
+ ### 2. SQL 规范
498
+
499
+ - **禁止 SELECT ***:明确指定需要的列
500
+ - **分页查询必须加 LIMIT**:避免全表查询
501
+ - **批量操作使用 batch**:MyBatis Plus 的 `saveBatch()` 方法
502
+ - **大表查询走索引**:通过 EXPLAIN 验证
503
+
504
+ ### 3. MyBatis Plus 使用
505
+
506
+ - **优先使用 LambdaQueryWrapper**:类型安全,重构友好
507
+ - **合理使用逻辑删除**:高频查询表注意索引包含 deleted 字段
508
+ - **Entity 实现 Serializable**:支持缓存序列化
509
+ - **使用自动填充**:createTime、updateTime 统一处理
510
+
511
+ ## 常见问题
512
+
513
+ ### 1. 连接池耗尽(Pool exhausted)
514
+
515
+ **原因**:并发量过大或连接泄漏
516
+
517
+ **解决**:
518
+ - 增大 `max-active` 配置
519
+ - 检查是否有未关闭的连接(使用 try-with-resources)
520
+ - 启用 Druid 的 `removeAbandoned` 配置回收泄漏连接
521
+ - 检查事务方法中是否有耗时操作占用连接
522
+
523
+ ### 2. 连接超时(Connection timeout)
524
+
525
+ **原因**:MySQL 服务端关闭了空闲连接
526
+
527
+ **解决**:
528
+ - 启用 `test-while-idle: true` 检测空闲连接
529
+ - 设置 `time-between-eviction-runs-millis` 小于 MySQL 的 `wait_timeout`
530
+ - 检查 MySQL `max_connections` 配置
531
+
532
+ ### 3. 慢查询导致性能问题
533
+
534
+ **原因**:缺少索引或 SQL 不合理
535
+
536
+ **解决**:
537
+ - 通过 Druid 监控面板定位慢 SQL
538
+ - 使用 EXPLAIN 分析执行计划
539
+ - 添加合适的索引
540
+ - 优化 SQL 写法,避免全表扫描
541
+
542
+ ### 4. MyBatis Plus 逻辑删除不生效
543
+
544
+ **原因**:配置缺失或字段注解错误
545
+
546
+ **解决**:
547
+ - 检查 `global-config.db-config.logic-delete-field` 配置
548
+ - 确保实体类字段添加 `@TableLogic` 注解
549
+ - 自定义 SQL 不会自动添加逻辑删除条件,需手动处理
550
+
551
+ ### 5. 批量插入性能差
552
+
553
+ **原因**:逐条插入产生大量 SQL
554
+
555
+ **解决**:
556
+ - 使用 `saveBatch()` 方法批量插入
557
+ - JDBC URL 添加 `rewriteBatchedStatements=true` 参数
558
+ - 控制每批次大小(推荐 500-1000 条)
559
+
560
+ ## 依赖版本
561
+
562
+ - Druid: 1.2.24
563
+ - MyBatis Plus: 3.5.15(mybatis-plus-spring-boot3-starter)
564
+ - MySQL Connector/J: 由 Spring Boot 3.5.3 BOM 管理
565
+ - Spring Boot: 3.5.3
566
+ - Java: 21
567
+
568
+ ## 参考文档
569
+
570
+ - [MyBatis Plus 官方文档](https://baomidou.com/pages/24112f/)
571
+ - [Druid 官方文档](https://github.com/alibaba/druid/wiki)
572
+ - [Spring Boot 数据访问](https://docs.spring.io/spring-boot/reference/data/sql.html)