ai-engineering-init 1.1.0
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.
- package/.claude/agents/code-reviewer.md +139 -0
- package/.claude/agents/project-manager.md +159 -0
- package/.claude/audio/completed.wav +0 -0
- package/.claude/commands/add-todo.md +255 -0
- package/.claude/commands/check.md +210 -0
- package/.claude/commands/crud.md +454 -0
- package/.claude/commands/dev.md +503 -0
- package/.claude/commands/init-docs.md +681 -0
- package/.claude/commands/next.md +251 -0
- package/.claude/commands/progress.md +242 -0
- package/.claude/commands/start.md +199 -0
- package/.claude/commands/sync.md +307 -0
- package/.claude/commands/update-status.md +428 -0
- package/.claude/docs/Mixin/344/275/277/347/224/250/346/214/207/345/215/227.md +299 -0
- package/.claude/docs/README.md +167 -0
- package/.claude/docs//345/211/215/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +599 -0
- package/.claude/docs//345/220/216/347/253/257/345/274/200/345/217/221/346/214/207/345/215/227.md +726 -0
- package/.claude/docs//345/267/245/344/275/234/346/265/201/345/274/200/345/217/221/346/214/207/345/215/227.md +714 -0
- package/.claude/docs//345/267/245/345/205/267/347/261/273/344/275/277/347/224/250/346/214/207/345/215/227.md +463 -0
- package/.claude/docs//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/350/247/204/350/214/203.md +390 -0
- package/.claude/docs//346/226/260/345/212/237/350/203/275/345/274/200/345/217/221/346/265/201/347/250/213/350/247/204/350/214/203.md +688 -0
- package/.claude/docs//346/226/260/351/241/271/347/233/256/345/274/200/345/217/221/346/265/201/347/250/213.md +365 -0
- package/.claude/docs//346/241/206/346/236/266/350/257/264/346/230/216.md +393 -0
- package/.claude/docs//350/267/257/347/224/261/351/205/215/347/275/256/346/214/207/345/215/227.md +246 -0
- package/.claude/framework-config.json +73 -0
- package/.claude/hooks/pre-tool-use.js +117 -0
- package/.claude/hooks/skill-forced-eval.js +167 -0
- package/.claude/hooks/stop.js +58 -0
- package/.claude/settings.json +41 -0
- package/.claude/skills/add-skill/SKILL.md +352 -0
- package/.claude/skills/api-development/SKILL.md +560 -0
- package/.claude/skills/architecture-design/SKILL.md +756 -0
- package/.claude/skills/backend-annotations/SKILL.md +674 -0
- package/.claude/skills/banana-image/CHANGELOG.md +37 -0
- package/.claude/skills/banana-image/README.md +146 -0
- package/.claude/skills/banana-image/SKILL.md +164 -0
- package/.claude/skills/banana-image/assets/logo.png +0 -0
- package/.claude/skills/banana-image/references/advanced-usage.md +189 -0
- package/.claude/skills/banana-image/scripts/apply_template.py +125 -0
- package/.claude/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.claude/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.claude/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.claude/skills/banana-image/scripts/package.json +18 -0
- package/.claude/skills/banana-image/scripts/requirements.txt +10 -0
- package/.claude/skills/banana-image/templates/poster.json +22 -0
- package/.claude/skills/banana-image/templates/product.json +17 -0
- package/.claude/skills/banana-image/templates/social.json +22 -0
- package/.claude/skills/banana-image/templates/thumbnail.json +17 -0
- package/.claude/skills/brainstorm/SKILL.md +648 -0
- package/.claude/skills/bug-detective/SKILL.md +1206 -0
- package/.claude/skills/code-patterns/SKILL.md +590 -0
- package/.claude/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.claude/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.claude/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.claude/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.claude/skills/crud-development/SKILL.md +649 -0
- package/.claude/skills/data-permission/SKILL.md +599 -0
- package/.claude/skills/database-ops/SKILL.md +407 -0
- package/.claude/skills/error-handler/SKILL.md +371 -0
- package/.claude/skills/file-oss-management/SKILL.md +863 -0
- package/.claude/skills/git-workflow/SKILL.md +375 -0
- package/.claude/skills/json-serialization/SKILL.md +357 -0
- package/.claude/skills/leniu-api-development/SKILL.md +803 -0
- package/.claude/skills/leniu-architecture-design/SKILL.md +598 -0
- package/.claude/skills/leniu-backend-annotations/SKILL.md +664 -0
- package/.claude/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.claude/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.claude/skills/leniu-data-permission/SKILL.md +256 -0
- package/.claude/skills/leniu-database-ops/SKILL.md +426 -0
- package/.claude/skills/leniu-error-handler/SKILL.md +462 -0
- package/.claude/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.claude/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.claude/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.claude/skills/leniu-java-entity/SKILL.md +751 -0
- package/.claude/skills/leniu-java-export/SKILL.md +560 -0
- package/.claude/skills/leniu-java-logging/SKILL.md +832 -0
- package/.claude/skills/leniu-java-mq/SKILL.md +338 -0
- package/.claude/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.claude/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.claude/skills/leniu-java-task/SKILL.md +367 -0
- package/.claude/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.claude/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.claude/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.claude/skills/leniu-mealtime/SKILL.md +215 -0
- package/.claude/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.claude/skills/leniu-security-guard/SKILL.md +520 -0
- package/.claude/skills/leniu-utils-toolkit/SKILL.md +380 -0
- package/.claude/skills/openspec-apply-change/SKILL.md +156 -0
- package/.claude/skills/openspec-archive-change/SKILL.md +114 -0
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.claude/skills/openspec-continue-change/SKILL.md +118 -0
- package/.claude/skills/openspec-explore/SKILL.md +290 -0
- package/.claude/skills/openspec-ff-change/SKILL.md +101 -0
- package/.claude/skills/openspec-new-change/SKILL.md +74 -0
- package/.claude/skills/openspec-onboard/SKILL.md +529 -0
- package/.claude/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.claude/skills/openspec-verify-change/SKILL.md +168 -0
- package/.claude/skills/performance-doctor/SKILL.md +627 -0
- package/.claude/skills/project-navigator/SKILL.md +305 -0
- package/.claude/skills/redis-cache/SKILL.md +839 -0
- package/.claude/skills/scheduled-jobs/SKILL.md +633 -0
- package/.claude/skills/security-guard/SKILL.md +748 -0
- package/.claude/skills/sms-mail/SKILL.md +766 -0
- package/.claude/skills/social-login/SKILL.md +668 -0
- package/.claude/skills/store-pc/SKILL.md +366 -0
- package/.claude/skills/task-tracker/SKILL.md +307 -0
- package/.claude/skills/tech-decision/SKILL.md +393 -0
- package/.claude/skills/tenant-management/SKILL.md +603 -0
- package/.claude/skills/test-development/SKILL.md +755 -0
- package/.claude/skills/ui-pc/SKILL.md +438 -0
- package/.claude/skills/utils-toolkit/SKILL.md +615 -0
- package/.claude/skills/websocket-sse/SKILL.md +716 -0
- package/.claude/skills/workflow-engine/SKILL.md +676 -0
- package/.claude/templates//345/276/205/345/212/236/346/270/205/345/215/225/346/250/241/346/235/277.md +56 -0
- package/.claude/templates//351/234/200/346/261/202/346/226/207/346/241/243/346/250/241/346/235/277.md +85 -0
- package/.claude/templates//351/241/271/347/233/256/347/212/266/346/200/201/346/250/241/346/235/277.md +43 -0
- package/.codex/skills/add-skill/SKILL.md +352 -0
- package/.codex/skills/add-todo/SKILL.md +269 -0
- package/.codex/skills/api-development/SKILL.md +693 -0
- package/.codex/skills/architecture-design/SKILL.md +628 -0
- package/.codex/skills/backend-annotations/SKILL.md +664 -0
- package/.codex/skills/banana-image/CHANGELOG.md +37 -0
- package/.codex/skills/banana-image/README.md +146 -0
- package/.codex/skills/banana-image/SKILL.md +164 -0
- package/.codex/skills/banana-image/assets/logo.png +0 -0
- package/.codex/skills/banana-image/references/advanced-usage.md +189 -0
- package/.codex/skills/banana-image/scripts/apply_template.py +125 -0
- package/.codex/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.codex/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.codex/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.codex/skills/banana-image/scripts/package.json +18 -0
- package/.codex/skills/banana-image/scripts/requirements.txt +10 -0
- package/.codex/skills/banana-image/templates/poster.json +22 -0
- package/.codex/skills/banana-image/templates/product.json +17 -0
- package/.codex/skills/banana-image/templates/social.json +22 -0
- package/.codex/skills/banana-image/templates/thumbnail.json +17 -0
- package/.codex/skills/brainstorm/SKILL.md +648 -0
- package/.codex/skills/bug-detective/SKILL.md +1206 -0
- package/.codex/skills/check/SKILL.md +367 -0
- package/.codex/skills/code-patterns/SKILL.md +442 -0
- package/.codex/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.codex/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.codex/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.codex/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.codex/skills/crud/SKILL.md +265 -0
- package/.codex/skills/crud-development/SKILL.md +637 -0
- package/.codex/skills/data-permission/SKILL.md +591 -0
- package/.codex/skills/database-ops/SKILL.md +553 -0
- package/.codex/skills/dev/SKILL.md +187 -0
- package/.codex/skills/error-handler/SKILL.md +361 -0
- package/.codex/skills/file-oss-management/SKILL.md +863 -0
- package/.codex/skills/git-workflow/SKILL.md +375 -0
- package/.codex/skills/init-docs/SKILL.md +194 -0
- package/.codex/skills/json-serialization/SKILL.md +357 -0
- package/.codex/skills/leniu-api-development/SKILL.md +803 -0
- package/.codex/skills/leniu-architecture-design/SKILL.md +594 -0
- package/.codex/skills/leniu-backend-annotations/SKILL.md +662 -0
- package/.codex/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.codex/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.codex/skills/leniu-data-permission/SKILL.md +256 -0
- package/.codex/skills/leniu-database-ops/SKILL.md +426 -0
- package/.codex/skills/leniu-error-handler/SKILL.md +462 -0
- package/.codex/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.codex/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.codex/skills/leniu-java-entity/SKILL.md +751 -0
- package/.codex/skills/leniu-java-export/SKILL.md +560 -0
- package/.codex/skills/leniu-java-logging/SKILL.md +832 -0
- package/.codex/skills/leniu-java-mq/SKILL.md +338 -0
- package/.codex/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.codex/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.codex/skills/leniu-java-task/SKILL.md +367 -0
- package/.codex/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.codex/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.codex/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.codex/skills/leniu-mealtime/SKILL.md +215 -0
- package/.codex/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.codex/skills/leniu-security-guard/SKILL.md +520 -0
- package/.codex/skills/leniu-utils-toolkit/SKILL.md +378 -0
- package/.codex/skills/next/SKILL.md +137 -0
- package/.codex/skills/openspec-apply-change/SKILL.md +156 -0
- package/.codex/skills/openspec-archive-change/SKILL.md +114 -0
- package/.codex/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.codex/skills/openspec-continue-change/SKILL.md +118 -0
- package/.codex/skills/openspec-explore/SKILL.md +290 -0
- package/.codex/skills/openspec-ff-change/SKILL.md +101 -0
- package/.codex/skills/openspec-new-change/SKILL.md +74 -0
- package/.codex/skills/openspec-onboard/SKILL.md +529 -0
- package/.codex/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.codex/skills/openspec-verify-change/SKILL.md +168 -0
- package/.codex/skills/performance-doctor/SKILL.md +627 -0
- package/.codex/skills/progress/SKILL.md +193 -0
- package/.codex/skills/project-navigator/SKILL.md +286 -0
- package/.codex/skills/redis-cache/SKILL.md +829 -0
- package/.codex/skills/scheduled-jobs/SKILL.md +633 -0
- package/.codex/skills/security-guard/SKILL.md +739 -0
- package/.codex/skills/sms-mail/SKILL.md +766 -0
- package/.codex/skills/social-login/SKILL.md +668 -0
- package/.codex/skills/start/SKILL.md +154 -0
- package/.codex/skills/store-pc/SKILL.md +491 -0
- package/.codex/skills/sync/SKILL.md +149 -0
- package/.codex/skills/task-tracker/SKILL.md +307 -0
- package/.codex/skills/tech-decision/SKILL.md +393 -0
- package/.codex/skills/tenant-management/SKILL.md +603 -0
- package/.codex/skills/test-development/SKILL.md +755 -0
- package/.codex/skills/ui-pc/SKILL.md +475 -0
- package/.codex/skills/update-status/SKILL.md +159 -0
- package/.codex/skills/utils-toolkit/SKILL.md +593 -0
- package/.codex/skills/websocket-sse/SKILL.md +716 -0
- package/.codex/skills/workflow-engine/SKILL.md +676 -0
- package/.cursor/agents/code-reviewer.md +139 -0
- package/.cursor/agents/project-manager.md +159 -0
- package/.cursor/commands/opsx-apply.md +152 -0
- package/.cursor/commands/opsx-archive.md +157 -0
- package/.cursor/commands/opsx-bulk-archive.md +242 -0
- package/.cursor/commands/opsx-continue.md +114 -0
- package/.cursor/commands/opsx-explore.md +174 -0
- package/.cursor/commands/opsx-ff.md +94 -0
- package/.cursor/commands/opsx-new.md +69 -0
- package/.cursor/commands/opsx-onboard.md +525 -0
- package/.cursor/commands/opsx-sync.md +134 -0
- package/.cursor/commands/opsx-verify.md +164 -0
- package/.cursor/mcp.json +22 -0
- package/.cursor/skills/add-skill/SKILL.md +352 -0
- package/.cursor/skills/api-development/SKILL.md +560 -0
- package/.cursor/skills/architecture-design/SKILL.md +756 -0
- package/.cursor/skills/backend-annotations/SKILL.md +674 -0
- package/.cursor/skills/banana-image/CHANGELOG.md +37 -0
- package/.cursor/skills/banana-image/README.md +146 -0
- package/.cursor/skills/banana-image/SKILL.md +164 -0
- package/.cursor/skills/banana-image/assets/logo.png +0 -0
- package/.cursor/skills/banana-image/references/advanced-usage.md +189 -0
- package/.cursor/skills/banana-image/scripts/apply_template.py +125 -0
- package/.cursor/skills/banana-image/scripts/banana_image_exec.ts +412 -0
- package/.cursor/skills/banana-image/scripts/batch_prep.py +82 -0
- package/.cursor/skills/banana-image/scripts/package-lock.json +1437 -0
- package/.cursor/skills/banana-image/scripts/package.json +18 -0
- package/.cursor/skills/banana-image/scripts/requirements.txt +10 -0
- package/.cursor/skills/banana-image/templates/poster.json +22 -0
- package/.cursor/skills/banana-image/templates/product.json +17 -0
- package/.cursor/skills/banana-image/templates/social.json +22 -0
- package/.cursor/skills/banana-image/templates/thumbnail.json +17 -0
- package/.cursor/skills/brainstorm/SKILL.md +648 -0
- package/.cursor/skills/bug-detective/SKILL.md +1206 -0
- package/.cursor/skills/code-patterns/SKILL.md +590 -0
- package/.cursor/skills/collaborating-with-codex/SKILL.md +174 -0
- package/.cursor/skills/collaborating-with-codex/scripts/codex_bridge.py +275 -0
- package/.cursor/skills/collaborating-with-gemini/SKILL.md +194 -0
- package/.cursor/skills/collaborating-with-gemini/scripts/gemini_bridge.py +275 -0
- package/.cursor/skills/crud-development/SKILL.md +649 -0
- package/.cursor/skills/data-permission/SKILL.md +599 -0
- package/.cursor/skills/database-ops/SKILL.md +407 -0
- package/.cursor/skills/error-handler/SKILL.md +371 -0
- package/.cursor/skills/file-oss-management/SKILL.md +863 -0
- package/.cursor/skills/git-workflow/SKILL.md +375 -0
- package/.cursor/skills/json-serialization/SKILL.md +357 -0
- package/.cursor/skills/leniu-api-development/SKILL.md +803 -0
- package/.cursor/skills/leniu-architecture-design/SKILL.md +598 -0
- package/.cursor/skills/leniu-backend-annotations/SKILL.md +664 -0
- package/.cursor/skills/leniu-code-patterns/SKILL.md +365 -0
- package/.cursor/skills/leniu-crud-development/SKILL.md +1110 -0
- package/.cursor/skills/leniu-data-permission/SKILL.md +256 -0
- package/.cursor/skills/leniu-database-ops/SKILL.md +426 -0
- package/.cursor/skills/leniu-error-handler/SKILL.md +462 -0
- package/.cursor/skills/leniu-java-amount-handling/SKILL.md +461 -0
- package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.cursor/skills/leniu-java-concurrent/SKILL.md +400 -0
- package/.cursor/skills/leniu-java-entity/SKILL.md +751 -0
- package/.cursor/skills/leniu-java-export/SKILL.md +560 -0
- package/.cursor/skills/leniu-java-logging/SKILL.md +832 -0
- package/.cursor/skills/leniu-java-mq/SKILL.md +338 -0
- package/.cursor/skills/leniu-java-mybatis/SKILL.md +640 -0
- package/.cursor/skills/leniu-java-report-query-param/SKILL.md +291 -0
- package/.cursor/skills/leniu-java-task/SKILL.md +367 -0
- package/.cursor/skills/leniu-java-total-line/SKILL.md +195 -0
- package/.cursor/skills/leniu-marketing-price-rule-customizer/SKILL.md +301 -0
- package/.cursor/skills/leniu-marketing-recharge-rule-customizer/SKILL.md +285 -0
- package/.cursor/skills/leniu-mealtime/SKILL.md +215 -0
- package/.cursor/skills/leniu-redis-cache/SKILL.md +316 -0
- package/.cursor/skills/leniu-security-guard/SKILL.md +520 -0
- package/.cursor/skills/leniu-utils-toolkit/SKILL.md +380 -0
- package/.cursor/skills/openspec-apply-change/SKILL.md +156 -0
- package/.cursor/skills/openspec-archive-change/SKILL.md +114 -0
- package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/.cursor/skills/openspec-continue-change/SKILL.md +118 -0
- package/.cursor/skills/openspec-explore/SKILL.md +290 -0
- package/.cursor/skills/openspec-ff-change/SKILL.md +101 -0
- package/.cursor/skills/openspec-new-change/SKILL.md +74 -0
- package/.cursor/skills/openspec-onboard/SKILL.md +529 -0
- package/.cursor/skills/openspec-sync-specs/SKILL.md +138 -0
- package/.cursor/skills/openspec-verify-change/SKILL.md +168 -0
- package/.cursor/skills/performance-doctor/SKILL.md +627 -0
- package/.cursor/skills/project-navigator/SKILL.md +305 -0
- package/.cursor/skills/redis-cache/SKILL.md +839 -0
- package/.cursor/skills/scheduled-jobs/SKILL.md +633 -0
- package/.cursor/skills/security-guard/SKILL.md +748 -0
- package/.cursor/skills/sms-mail/SKILL.md +766 -0
- package/.cursor/skills/social-login/SKILL.md +668 -0
- package/.cursor/skills/store-pc/SKILL.md +366 -0
- package/.cursor/skills/task-tracker/SKILL.md +307 -0
- package/.cursor/skills/tech-decision/SKILL.md +393 -0
- package/.cursor/skills/tenant-management/SKILL.md +603 -0
- package/.cursor/skills/test-development/SKILL.md +755 -0
- package/.cursor/skills/ui-pc/SKILL.md +438 -0
- package/.cursor/skills/utils-toolkit/SKILL.md +615 -0
- package/.cursor/skills/websocket-sse/SKILL.md +716 -0
- package/.cursor/skills/workflow-engine/SKILL.md +676 -0
- package/AGENTS.md +669 -0
- package/CLAUDE.md +205 -0
- package/README.md +205 -0
- package/bin/index.js +179 -0
- package/init.sh +178 -0
- package/package.json +27 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# leniu-data-permission
|
|
2
|
+
|
|
3
|
+
适用于 leniu-tengyun-core 项目的多租户数据权限控制。
|
|
4
|
+
|
|
5
|
+
## 双库架构
|
|
6
|
+
|
|
7
|
+
leniu-tengyun-core 采用物理数据库隔离的多租户架构,每个租户拥有独立的业务数据库:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
系统库 (system)
|
|
11
|
+
├── 租户配置表
|
|
12
|
+
├── 系统字典表
|
|
13
|
+
└── ... 系统级配置
|
|
14
|
+
|
|
15
|
+
租户库 (tenant_1, tenant_2, ...)
|
|
16
|
+
├── 租户业务数据
|
|
17
|
+
└── ... 业务表(无 tenant_id 字段)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 数据源切换
|
|
21
|
+
|
|
22
|
+
### 注解方式
|
|
23
|
+
|
|
24
|
+
| 注解 | 用途 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| `@UseSystem` | 切换到系统库 |
|
|
27
|
+
| `@UseGlobalTs("dbName")` | 切换到全局时序库 |
|
|
28
|
+
|
|
29
|
+
```java
|
|
30
|
+
import net.xnzn.framework.data.mybatis.datasource.UseSystem;
|
|
31
|
+
import net.xnzn.framework.data.mybatis.datasource.UseGlobalTs;
|
|
32
|
+
|
|
33
|
+
@Service
|
|
34
|
+
public class TenantConfigService {
|
|
35
|
+
|
|
36
|
+
// 操作系统库
|
|
37
|
+
@UseSystem
|
|
38
|
+
public TenantConfig getTenantConfig(Long tenantId) {
|
|
39
|
+
return tenantConfigMapper.selectById(tenantId);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 操作全局时序库
|
|
43
|
+
@UseGlobalTs("ts_db_name")
|
|
44
|
+
public List<TimeSeriesData> getTimeSeries(String key) {
|
|
45
|
+
return timeSeriesMapper.selectList(...);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 编程方式
|
|
51
|
+
|
|
52
|
+
```java
|
|
53
|
+
import net.xnzn.framework.data.dataset.Executors;
|
|
54
|
+
|
|
55
|
+
// 在指定租户库中执行操作
|
|
56
|
+
Executors.doInTenant(tenantId, status -> {
|
|
57
|
+
// 这里的操作会在 tenantId 对应的数据库中执行
|
|
58
|
+
businessDataMapper.insert(data);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// 读取指定租户数据(不开启事务)
|
|
62
|
+
List<Data> data = Executors.readInTenant(tenantId, () -> {
|
|
63
|
+
return businessDataMapper.selectList(...);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 遍历所有租户执行任务
|
|
67
|
+
Executors.doInAllTenant(tenantId -> {
|
|
68
|
+
// 对每个租户执行此操作
|
|
69
|
+
businessDataMapper.delete(...);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// 遍历所有租户执行任务(出错继续)
|
|
73
|
+
Executors.doInAllTenant(true, tenantId -> {
|
|
74
|
+
// 某个租户出错不影响其他租户
|
|
75
|
+
businessDataMapper.update(...);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// 在系统库中执行操作
|
|
79
|
+
Executors.doInSystem(status -> {
|
|
80
|
+
// 这里的操作会在系统库中执行
|
|
81
|
+
systemConfigMapper.insert(config);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 读取系统库数据
|
|
85
|
+
SystemConfig config = Executors.readInSystem(() -> {
|
|
86
|
+
return systemConfigMapper.selectById(1);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 在全局时序库中执行
|
|
90
|
+
Executors.doInGlobalTs("ts_db_name", false, () -> {
|
|
91
|
+
timeSeriesMapper.insert(data);
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 租户上下文
|
|
96
|
+
|
|
97
|
+
### TenantContextHolder
|
|
98
|
+
|
|
99
|
+
```java
|
|
100
|
+
import net.xnzn.framework.data.tenant.TenantContextHolder;
|
|
101
|
+
|
|
102
|
+
// 获取当前租户 ID(来自请求头)
|
|
103
|
+
Long tenantId = TenantContextHolder.getTenantId();
|
|
104
|
+
|
|
105
|
+
// 设置租户 ID(一般由 Filter 自动设置)
|
|
106
|
+
TenantContextHolder.setTenantId(123L);
|
|
107
|
+
|
|
108
|
+
// 清除租户上下文
|
|
109
|
+
TenantContextHolder.clear();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 租户请求头
|
|
113
|
+
|
|
114
|
+
默认租户 ID 请求头名称为 `MERCHANT-ID`(可配置):
|
|
115
|
+
|
|
116
|
+
```http
|
|
117
|
+
GET /api/v2/users HTTP/1.1
|
|
118
|
+
MERCHANT-ID: 12345
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 数据源路由
|
|
122
|
+
|
|
123
|
+
### RoutingRule
|
|
124
|
+
|
|
125
|
+
```java
|
|
126
|
+
import net.xnzn.framework.data.dataset.rule.RoutingRule;
|
|
127
|
+
|
|
128
|
+
// 获取当前路由上下文
|
|
129
|
+
RoutingRule.Context context = RoutingRule.getContext();
|
|
130
|
+
|
|
131
|
+
// 重置路由规则
|
|
132
|
+
RoutingRule.reset();
|
|
133
|
+
|
|
134
|
+
// 使用系统库
|
|
135
|
+
RoutingRule.useSystem();
|
|
136
|
+
|
|
137
|
+
// 使用全局时序库
|
|
138
|
+
RoutingRule.useGlobalTs("ts_db_name");
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 路由规则加载
|
|
142
|
+
|
|
143
|
+
数据源规则从配置文件加载:
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
spring:
|
|
147
|
+
dataset:
|
|
148
|
+
system:
|
|
149
|
+
master:
|
|
150
|
+
jdbc-url: jdbc:mysql://localhost:3306/system_db
|
|
151
|
+
username: root
|
|
152
|
+
password: xxx
|
|
153
|
+
slave:
|
|
154
|
+
- jdbc-url: jdbc:mysql://slave1:3306/system_db
|
|
155
|
+
- jdbc-url: jdbc:mysql://slave2:3306/system_db
|
|
156
|
+
global-ts:
|
|
157
|
+
master:
|
|
158
|
+
jdbc-url: jdbc:mysql://localhost:3306/ts_db
|
|
159
|
+
business:
|
|
160
|
+
tenant_1:
|
|
161
|
+
master:
|
|
162
|
+
jdbc-url: jdbc:mysql://localhost:3306/tenant_1
|
|
163
|
+
slave:
|
|
164
|
+
- jdbc-url: jdbc:mysql://slave1:3306/tenant_1
|
|
165
|
+
tenant_2:
|
|
166
|
+
master:
|
|
167
|
+
jdbc-url: jdbc:mysql://localhost:3306/tenant_2
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 典型场景
|
|
171
|
+
|
|
172
|
+
### 跨租户查询
|
|
173
|
+
|
|
174
|
+
```java
|
|
175
|
+
@Service
|
|
176
|
+
public class CrossTenantService {
|
|
177
|
+
|
|
178
|
+
// 查询多个租户的数据
|
|
179
|
+
public Map<Long, List<Order>> getOrdersByTenants(List<Long> tenantIds) {
|
|
180
|
+
Map<Long, List<Order>> result = new HashMap<>();
|
|
181
|
+
for (Long tenantId : tenantIds) {
|
|
182
|
+
List<Order> orders = Executors.readInTenant(tenantId, () ->
|
|
183
|
+
orderMapper.selectList(new QueryWrapper<>())
|
|
184
|
+
);
|
|
185
|
+
result.put(tenantId, orders);
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 系统配置读取
|
|
193
|
+
|
|
194
|
+
```java
|
|
195
|
+
@Service
|
|
196
|
+
public class SystemConfigService {
|
|
197
|
+
|
|
198
|
+
@UseSystem
|
|
199
|
+
public SystemConfig getConfig(String key) {
|
|
200
|
+
return systemConfigMapper.selectOne(
|
|
201
|
+
new QueryWrapper<SystemConfig>().eq("config_key", key)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 租户数据初始化
|
|
208
|
+
|
|
209
|
+
```java
|
|
210
|
+
@Service
|
|
211
|
+
public class TenantInitService {
|
|
212
|
+
|
|
213
|
+
// 为新租户初始化数据
|
|
214
|
+
public void initTenant(Long tenantId) {
|
|
215
|
+
Executors.doInTenant(tenantId, status -> {
|
|
216
|
+
// 创建默认菜单
|
|
217
|
+
defaultMenuService.createDefaultMenus();
|
|
218
|
+
// 创建默认角色
|
|
219
|
+
defaultRoleService.createDefaultRoles();
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## TenantConfigProperties
|
|
226
|
+
|
|
227
|
+
```java
|
|
228
|
+
@Setter
|
|
229
|
+
@Getter
|
|
230
|
+
@ConfigurationProperties(prefix = "leniu.tenant")
|
|
231
|
+
public class TenantConfigProperties {
|
|
232
|
+
// 请求头名称,默认 MERCHANT-ID
|
|
233
|
+
private String carrierName = "MERCHANT-ID";
|
|
234
|
+
|
|
235
|
+
// MDC 键名
|
|
236
|
+
private String mdc = "tenantId";
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## 与 RuoYi-Plus 的区别
|
|
241
|
+
|
|
242
|
+
| 特性 | RuoYi-Plus | leniu-tengyun-core |
|
|
243
|
+
|------|-----------|-------------------|
|
|
244
|
+
| 多租户方式 | 逻辑隔离(tenant_id 字段) | 物理隔离(独立数据库) |
|
|
245
|
+
| 租户切换 | `@TenantLine` 注解 | `@UseSystem` / `Executors.doInTenant()` |
|
|
246
|
+
| 租户上下文 | `TenantLineHelper.tenantId()` | `TenantContextHolder.getTenantId()` |
|
|
247
|
+
| 数据权限 | `@DataColumn` 注解 | 物理库隔离,无需字段 |
|
|
248
|
+
| 系统库操作 | `@TenantLine` 指定 "000000" | `@UseSystem` 或 `Executors.doInSystem()` |
|
|
249
|
+
|
|
250
|
+
## 注意事项
|
|
251
|
+
|
|
252
|
+
1. leniu 采用物理库隔离,表中无 `tenant_id` 字段
|
|
253
|
+
2. 默认操作租户库,需要访问系统库时必须明确切换
|
|
254
|
+
3. 跨租户操作需要使用 `Executors.doInTenant()` 或 `Executors.readInTenant()`
|
|
255
|
+
4. 事务会在方法执行结束后自动切回原来的数据源
|
|
256
|
+
5. `TenantContextHolderFilter` 自动从请求头解析租户 ID
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: leniu-database-ops
|
|
3
|
+
description: |
|
|
4
|
+
leniu-yunshitang-core 项目数据库操作规范。包含建表模板、Entity 实体类模板、双库架构设计模式、审计字段、逻辑删除。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 创建 leniu 数据库表(MySQL)
|
|
8
|
+
- 设计 Entity 实体类(审计字段、逻辑删除)
|
|
9
|
+
- 配置逻辑删除、乐观锁
|
|
10
|
+
- 双库架构(系统库+商户库)设计
|
|
11
|
+
- 表字段设计
|
|
12
|
+
|
|
13
|
+
适用项目:leniu-tengyun-core(云食堂项目)
|
|
14
|
+
|
|
15
|
+
触发词:leniu-数据库、leniu-SQL、leniu-建表、leniu-Entity、leniu-双库、leniu-商户库、leniu-系统库、net.xnzn、leniu-yunshitang、云食堂数据库
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# leniu-yunshitang-core 数据库操作规范
|
|
19
|
+
|
|
20
|
+
## 项目概述
|
|
21
|
+
|
|
22
|
+
leniu-yunshitang-core 是基于 **pigx-framework** 的智慧食堂云服务平台,采用**双库架构**(系统库 + 商户库)实现多租户隔离。
|
|
23
|
+
|
|
24
|
+
| 项目 | 路径 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| **云食堂后端** | `/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun-core` |
|
|
27
|
+
| **包名前缀** | `net.xnzn.*` |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 核心架构差异
|
|
32
|
+
|
|
33
|
+
| 对比项 | leniu-tengyun-core |
|
|
34
|
+
|--------|-------------------|
|
|
35
|
+
| **包名前缀** | `net.xnzn.*` |
|
|
36
|
+
| **数据库** | MySQL 8.0+ |
|
|
37
|
+
| **租户模式** | **双库架构**(系统库 + 商户库) |
|
|
38
|
+
| **Entity 基类** | 无基类(自定义审计字段) |
|
|
39
|
+
| **主键策略** | 雪花ID 或 自增ID |
|
|
40
|
+
| **逻辑删除** | `del_flag` (1=删除, 2=正常) |
|
|
41
|
+
| **审计字段** | `crby/crtime/upby/uptime` |
|
|
42
|
+
| **租户字段** | **无 tenant_id 字段**(双库隔离) |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 1. 双库架构设计
|
|
47
|
+
|
|
48
|
+
### 架构说明
|
|
49
|
+
|
|
50
|
+
本项目采用**物理分离的双库架构**,而非单库多租户:
|
|
51
|
+
|
|
52
|
+
| 库类型 | 说明 | 数据范围 | 访问方式 |
|
|
53
|
+
|--------|------|---------|---------|
|
|
54
|
+
| **系统库** | 全局系统数据 | 租户信息、商户配置、系统字典等 | 默认访问(无 MERCHANT-ID) |
|
|
55
|
+
| **商户库** | 租户业务数据 | 订单、菜品、用户、设备等商户数据 | 请求头携带 MERCHANT-ID 时访问 |
|
|
56
|
+
|
|
57
|
+
**关键区别**:
|
|
58
|
+
- Entity 不需要 `tenant_id` 字段(物理库隔离)
|
|
59
|
+
- 通过 `TenantContextHolder.getTenantId()` 获取当前租户
|
|
60
|
+
- 使用 `Executors.doInTenant()` / `doInSystem()` 切换库
|
|
61
|
+
|
|
62
|
+
### 双库配置示例
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# bootstrap.yml
|
|
66
|
+
dataset:
|
|
67
|
+
system:
|
|
68
|
+
master:
|
|
69
|
+
jdbcUrl: jdbc:mysql://${MYSQL_HOST:mysql}:${MYSQL_PORT:3306}/system
|
|
70
|
+
username: ${MYSQL_USERNAME:root}
|
|
71
|
+
password: ${MYSQL_PASSWORD:do@u.can}
|
|
72
|
+
|
|
73
|
+
tenant:
|
|
74
|
+
carrier-name: MERCHANT-ID
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 多租户上下文
|
|
78
|
+
|
|
79
|
+
```java
|
|
80
|
+
// 获取当前租户ID
|
|
81
|
+
Long tenantId = TenantContextHolder.getTenantId();
|
|
82
|
+
|
|
83
|
+
// 在指定租户库执行操作
|
|
84
|
+
Executors.doInTenant(tenantId, () -> {
|
|
85
|
+
// 业务代码 - 访问商户库
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// 在系统库执行操作
|
|
89
|
+
Executors.doInSystem(() -> {
|
|
90
|
+
// 业务代码 - 访问系统库
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// 遍历所有租户执行
|
|
94
|
+
Executors.doInAllTenant(tenantId -> {
|
|
95
|
+
// 业务代码
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 2. Entity 实体类模板(带审计字段)
|
|
102
|
+
|
|
103
|
+
```java
|
|
104
|
+
package net.xnzn.core.xxx.model;
|
|
105
|
+
|
|
106
|
+
import com.baomidou.mybatisplus.annotation.*;
|
|
107
|
+
import io.swagger.annotations.ApiModel;
|
|
108
|
+
import io.swagger.annotations.ApiModelProperty;
|
|
109
|
+
import lombok.Data;
|
|
110
|
+
import lombok.experimental.Accessors;
|
|
111
|
+
|
|
112
|
+
import java.io.Serializable;
|
|
113
|
+
import java.time.LocalDateTime;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* XXX 对象
|
|
117
|
+
*/
|
|
118
|
+
@Data
|
|
119
|
+
@Accessors(chain = true)
|
|
120
|
+
@TableName("xxx_table")
|
|
121
|
+
@ApiModel(value = "XXX对象", description = "XXX表")
|
|
122
|
+
public class XxxEntity implements Serializable {
|
|
123
|
+
|
|
124
|
+
private static final long serialVersionUID = 1L;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 主键 ID
|
|
128
|
+
*/
|
|
129
|
+
@ApiModelProperty("主键ID")
|
|
130
|
+
@TableId(value = "id", type = IdType.AUTO)
|
|
131
|
+
private Long id;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 业务字段 - 名称
|
|
135
|
+
*/
|
|
136
|
+
@ApiModelProperty("名称")
|
|
137
|
+
@TableField("name")
|
|
138
|
+
private String name;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 业务字段 - 状态
|
|
142
|
+
*/
|
|
143
|
+
@ApiModelProperty("状态")
|
|
144
|
+
@TableField("status")
|
|
145
|
+
private Integer status;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 删除标识(1删除,2正常)
|
|
149
|
+
* ⚠️ 注意:与 RuoYi 相反!
|
|
150
|
+
*/
|
|
151
|
+
@ApiModelProperty("删除标识(1删除,2正常)")
|
|
152
|
+
@TableField("del_flag")
|
|
153
|
+
private Integer delFlag;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 乐观锁
|
|
157
|
+
*/
|
|
158
|
+
@ApiModelProperty("乐观锁")
|
|
159
|
+
@TableField("revision")
|
|
160
|
+
private Integer revision;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 创建人
|
|
164
|
+
*/
|
|
165
|
+
@ApiModelProperty("创建人")
|
|
166
|
+
@TableField(value = "crby", fill = FieldFill.INSERT)
|
|
167
|
+
private String crby;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 创建时间
|
|
171
|
+
*/
|
|
172
|
+
@ApiModelProperty("创建时间")
|
|
173
|
+
@TableField(value = "crtime", fill = FieldFill.INSERT)
|
|
174
|
+
private LocalDateTime crtime;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 更新人
|
|
178
|
+
*/
|
|
179
|
+
@ApiModelProperty("更新人")
|
|
180
|
+
@TableField(value = "upby", fill = FieldFill.INSERT_UPDATE)
|
|
181
|
+
private String upby;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 更新时间
|
|
185
|
+
*/
|
|
186
|
+
@ApiModelProperty("更新时间")
|
|
187
|
+
@TableField(value = "uptime", fill = FieldFill.INSERT_UPDATE)
|
|
188
|
+
private LocalDateTime uptime;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 3. MySQL CREATE TABLE 模板
|
|
195
|
+
|
|
196
|
+
```sql
|
|
197
|
+
CREATE TABLE `xxx_table` (
|
|
198
|
+
-- 主键
|
|
199
|
+
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
200
|
+
|
|
201
|
+
-- ⚠️ 注意:双库架构不需要 tenant_id 字段!
|
|
202
|
+
|
|
203
|
+
-- 业务字段
|
|
204
|
+
`name` VARCHAR(100) NOT NULL COMMENT '名称',
|
|
205
|
+
`status` TINYINT(1) DEFAULT 1 COMMENT '状态(0停用 1启用)',
|
|
206
|
+
|
|
207
|
+
-- 版本和删除
|
|
208
|
+
`revision` INT DEFAULT 0 COMMENT '乐观锁版本号',
|
|
209
|
+
`del_flag` TINYINT(1) DEFAULT 2 COMMENT '删除标识(1删除 2正常)',
|
|
210
|
+
|
|
211
|
+
-- 审计字段
|
|
212
|
+
`crby` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
|
|
213
|
+
`crtime` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
214
|
+
`upby` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
|
|
215
|
+
`uptime` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
216
|
+
|
|
217
|
+
PRIMARY KEY (`id`),
|
|
218
|
+
KEY `idx_status` (`status`),
|
|
219
|
+
KEY `idx_crtime` (`crtime`),
|
|
220
|
+
KEY `idx_del_flag` (`del_flag`)
|
|
221
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='XXX表';
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 4. 八大数据库设计模式
|
|
227
|
+
|
|
228
|
+
### 模式一:双库多租户
|
|
229
|
+
|
|
230
|
+
```java
|
|
231
|
+
// ⚠️ 双库架构:Entity 不需要 tenant_id 字段
|
|
232
|
+
// 租户隔离通过物理库实现,而非 tenant_id 字段
|
|
233
|
+
|
|
234
|
+
// 获取当前租户ID(从上下文获取,而非 Entity 字段)
|
|
235
|
+
Long tenantId = TenantContextHolder.getTenantId();
|
|
236
|
+
|
|
237
|
+
// 查询时自动路由到对应租户库
|
|
238
|
+
List<XxxEntity> list = xxxMapper.selectList(wrapper);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**使用场景**:所有需要租户隔离的业务表
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### 模式二:树结构 - 祖先路径法(推荐)
|
|
246
|
+
|
|
247
|
+
```sql
|
|
248
|
+
CREATE TABLE demo_tree (
|
|
249
|
+
id BIGINT NOT NULL,
|
|
250
|
+
parent_id BIGINT,
|
|
251
|
+
ancestors VARCHAR(500), -- 祖先路径:0,1,2,3
|
|
252
|
+
name VARCHAR(100),
|
|
253
|
+
del_flag TINYINT DEFAULT 2,
|
|
254
|
+
PRIMARY KEY (id),
|
|
255
|
+
INDEX idx_ancestors (ancestors)
|
|
256
|
+
) COMMENT='树形表';
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
### 模式三:树结构 - 简单父子法
|
|
262
|
+
|
|
263
|
+
```sql
|
|
264
|
+
CREATE TABLE demo_tree_simple (
|
|
265
|
+
id BIGINT NOT NULL,
|
|
266
|
+
parent_id BIGINT,
|
|
267
|
+
name VARCHAR(100),
|
|
268
|
+
del_flag TINYINT DEFAULT 2,
|
|
269
|
+
PRIMARY KEY (id)
|
|
270
|
+
) COMMENT='简单树形表';
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### 模式四:逻辑删除
|
|
276
|
+
|
|
277
|
+
```java
|
|
278
|
+
// Java Entity 中
|
|
279
|
+
@TableField("del_flag")
|
|
280
|
+
private Integer delFlag; // 1=删除,2=正常(注意与 RuoYi 相反!)
|
|
281
|
+
|
|
282
|
+
// MyBatis-Plus 查询时需要手动添加
|
|
283
|
+
wrapper.eq(XxxEntity::getDelFlag, 2);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### 模式五:审计追踪(自动填充)
|
|
289
|
+
|
|
290
|
+
```sql
|
|
291
|
+
CREATE TABLE demo_audit (
|
|
292
|
+
id BIGINT NOT NULL,
|
|
293
|
+
crby VARCHAR(64), -- 创建人(自动填充)
|
|
294
|
+
crtime DATETIME, -- 创建时间(自动填充)
|
|
295
|
+
upby VARCHAR(64), -- 更新人(自动填充)
|
|
296
|
+
uptime DATETIME, -- 更新时间(自动填充)
|
|
297
|
+
PRIMARY KEY (id)
|
|
298
|
+
) COMMENT='带审计的表';
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### 模式六:状态字段
|
|
304
|
+
|
|
305
|
+
```java
|
|
306
|
+
@ApiModelProperty("状态")
|
|
307
|
+
@TableField("status")
|
|
308
|
+
private Integer status; // 0=停用,1=启用
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### 模式七:数据权限控制
|
|
314
|
+
|
|
315
|
+
```java
|
|
316
|
+
// leniu 项目通常在 Service 层进行权限过滤
|
|
317
|
+
// 通过 mgrAuthApi.getUserAuthPO() 获取用户权限
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### 模式八:跨数据库兼容
|
|
323
|
+
|
|
324
|
+
| 场景 | MySQL | PostgreSQL | Oracle |
|
|
325
|
+
|------|-------|-----------|--------|
|
|
326
|
+
| 查询 Long 字段 | `LIKE` | `CAST AS VARCHAR` | `TO_CHAR()` |
|
|
327
|
+
| 主键策略 | 雪花ID/自增 | 同 | 同 |
|
|
328
|
+
| 日期函数 | `CURRENT_TIMESTAMP` | `NOW()` | `SYSDATE` |
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 5. 审计字段说明
|
|
333
|
+
|
|
334
|
+
| 字段 | 含义 | 类型 | 自动填充 |
|
|
335
|
+
|------|------|------|---------|
|
|
336
|
+
| `crby` | 创建人 | VARCHAR(64) | INSERT |
|
|
337
|
+
| `crtime` | 创建时间 | DATETIME | INSERT |
|
|
338
|
+
| `upby` | 更新人 | VARCHAR(64) | INSERT_UPDATE |
|
|
339
|
+
| `uptime` | 更新时间 | DATETIME | INSERT_UPDATE |
|
|
340
|
+
|
|
341
|
+
**注意**:
|
|
342
|
+
- `del_flag` 值与 RuoYi-Vue-Plus 相反!
|
|
343
|
+
- leniu:1=删除,2=正常
|
|
344
|
+
- RuoYi:0=正常,1=删除
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## 6. 常见错误对比
|
|
349
|
+
|
|
350
|
+
### ❌ 不要做
|
|
351
|
+
|
|
352
|
+
```sql
|
|
353
|
+
-- 错误1: 使用 tenant_id 字段(双库架构不需要)
|
|
354
|
+
tenant_id VARCHAR(20) DEFAULT '000000', -- ❌ 双库架构不需要!
|
|
355
|
+
|
|
356
|
+
-- 错误2: 使用错误的 del_flag 值
|
|
357
|
+
del_flag TINYINT DEFAULT 0, -- ❌ leniu 中 2=正常
|
|
358
|
+
|
|
359
|
+
-- 错误3: 使用 RuoYi 审计字段命名
|
|
360
|
+
create_by BIGINT, -- ❌ 应该用 crby
|
|
361
|
+
create_time DATETIME, -- ❌ 应该用 crtime
|
|
362
|
+
|
|
363
|
+
-- 错误4: COMMENT 使用英文
|
|
364
|
+
`user_name` VARCHAR(50) COMMENT 'user name', -- ❌ 禁止英文!
|
|
365
|
+
|
|
366
|
+
-- 错误5: 字段名不规范
|
|
367
|
+
userName VARCHAR(50) -- ❌ 应该用 user_name
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### ✅ 正确做法
|
|
371
|
+
|
|
372
|
+
```sql
|
|
373
|
+
-- 正确1: 双库架构不需要 tenant_id
|
|
374
|
+
-- (直接省略该字段)
|
|
375
|
+
|
|
376
|
+
-- 正确2: 使用正确的 del_flag 值
|
|
377
|
+
del_flag TINYINT DEFAULT 2 COMMENT '删除标识(1删除 2正常)', -- ✅
|
|
378
|
+
|
|
379
|
+
-- 正确3: 使用 leniu 审计字段命名
|
|
380
|
+
crby VARCHAR(64) DEFAULT NULL COMMENT '创建人', -- ✅
|
|
381
|
+
crtime DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', -- ✅
|
|
382
|
+
|
|
383
|
+
-- 正确4: COMMENT 使用中文
|
|
384
|
+
`user_name` VARCHAR(50) COMMENT '用户名', -- ✅
|
|
385
|
+
|
|
386
|
+
-- 正确5: 字段名使用蛇形命名法
|
|
387
|
+
user_name VARCHAR(50) -- ✅
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## 7. 检查清单
|
|
393
|
+
|
|
394
|
+
建表前必须检查:
|
|
395
|
+
|
|
396
|
+
- [ ] **主键是否是 BIGINT(20)**?(支持雪花ID或自增)
|
|
397
|
+
- [ ] **是否不需要 tenant_id 字段**?(双库架构)
|
|
398
|
+
- [ ] **是否有 del_flag TINYINT 字段**?(1=删除,2=正常)
|
|
399
|
+
- [ ] **是否有 revision INT 字段**?(乐观锁)
|
|
400
|
+
- [ ] **是否有完整的审计字段**?(crby, crtime, upby, uptime)
|
|
401
|
+
- [ ] **字段名是否全部使用蛇形命名法**?
|
|
402
|
+
- [ ] **所有字段是否有注释**?
|
|
403
|
+
- [ ] **所有 COMMENT 是否使用中文**?
|
|
404
|
+
- [ ] **Entity 审计字段是否配置了 FieldFill**?
|
|
405
|
+
- [ ] **Entity 是否正确使用了 @TableName 注解**?
|
|
406
|
+
- [ ] **Mapper XML 是否与 Java 文件同目录**?
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## 8. SQL 文件位置
|
|
411
|
+
|
|
412
|
+
| 数据库 | 脚本位置 |
|
|
413
|
+
|--------|---------|
|
|
414
|
+
| MySQL | 根据实际项目配置位置存放 |
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## 参考代码位置
|
|
419
|
+
|
|
420
|
+
| 类型 | 路径 |
|
|
421
|
+
|------|------|
|
|
422
|
+
| Entity 示例 | `core-bus/.../model/BusLine.java` |
|
|
423
|
+
| Mapper 示例 | `core-bus/.../mapper/BusLineMapper.java` |
|
|
424
|
+
| 配置文件 | `core-common/src/main/resources/bootstrap.yml` |
|
|
425
|
+
|
|
426
|
+
**项目路径**:`/Users/xujiajun/Developer/gongsi_proj/leniu-api/leniu-tengyun-core`
|