# Database 模块开发指南 单表 CRUD → REST 接口快速实现框架。基于 JPA + Fenix + QueryDSL + MapStruct。 ## 架构 ``` Controller (REST) → Service (业务) → Repository (数据访问) → Entity (模型) ``` ### 组件结构 | 包 | 组件 | 职责 | |---|---|---| | entity | IdOnlyEntity, SimpleEntity | 实体基类 | | entity | SnowflakeId, SnowflakeIdGenerator | ID 生成 | | entity | Query, GlobalResponse, Page | 查询/响应封装 | | repository | SimpleRepository | 统一数据访问接口 | | service | SaveService, QueryService, RemoveService | 功能接口 | | service | SimpleService, SimpleServiceSupport | 组合接口与实现 | | service | QueryParser | 查询条件解析 | | controller | SaveController, QueryController, RemoveController | REST 接口 | | controller | SimpleController, SimpleControllerSupport | 组合接口与实现 | | helper | DatabaseHelper, SnowflakeHelper | 工具类 | | exception | *Exception | 异常定义 | ## 核心设计 ### 实体继承 ``` IdOnlyEntity (id: Long, @SnowflakeId) ↑ SimpleEntity (+ createdTime, modifiedTime) ↑ 业务实体 (@Entity) ``` **实现要点**: - `@MappedSuperclass` 标记基类 - `@SnowflakeId` 触发 `SnowflakeIdGenerator` 生成 ID - `@CreatedDate/@LastModifiedDate` + `AuditingEntityListener` 自动填充时间 ### Repository ```java @NoRepositoryBean public interface SimpleRepository extends FenixJpaRepository, // CRUD + Fenix FenixJpaSpecificationExecutor, // Specification ListQueryByExampleExecutor, // Example ListQuerydslPredicateExecutor {} // QueryDSL ``` **核心能力**: - `saveOrUpdateByNotNullProperties()` - 部分字段更新 - Specification - 动态条件查询 - QueryDSL - 类型安全查询 ### Service 接口组合 ```java SaveService // save(entity), save(entities) QueryService // detail(id), list(), list(query), count() RemoveService // remove(id), remove(ids) SimpleService extends SaveService, QueryService, RemoveService ``` **SimpleServiceSupport 实现**: - 保存:Fenix `saveOrUpdateByNotNullProperties()` - 查询:JPA Criteria + Specification - 删除:`deleteBatchByIds()` - 扩展点:重写 `commonPredicates()` 添加全局过滤条件 ### Controller 接口组合 ```java SaveController // POST /save QueryController // GET/POST /list, GET /detail/{id} RemoveController // GET /remove/{id} SimpleController ``` **SimpleControllerSupport 实现**: - 调用 Service 方法 - 通过 Mapper 转换 DTO ↔ Entity - 封装 GlobalResponse - 扩展点:实现 `saveItemMapper()`, `listItemMapper()`, `detailItemMapper()` ### 查询条件 **Query 结构**:`Query(query: Queryable, sort: List, page: Pageable)` **QueryParser**:抽象类定义解析接口,`JpaQueryParser` 转换为 JPA Predicate **支持操作**: | 类别 | 操作 | |---|---| | 空值 | nullEqual, notNullEqual, empty, notEmpty | | 相等 | equal, notEqual | | 模糊 | like, notLike, contain, notContain | | 前后缀 | startWith, endWith, notStartWith, notEndWith | | 比较 | great, less, greatEqual, lessEqual | | 区间 | between, notBetween | | 集合 | inside, notInside | **实现**:JPA CriteriaBuilder 构建,支持多级字段路径(如 `user.name`),自动类型转换(枚举、LocalDateTime) ### 响应格式 ```java GlobalResponse(status, message, data) // status: 0 成功, 500 失败 // 列表: data = ListItem(items, total) // 详情: data = DetailItem(item) ``` ## 技术细节 ### 雪花算法 `SnowflakeHelper`:64 位 Long,1 位符号 + 41 位时间戳 + 10 位机器 ID + 12 位序列号 `SnowflakeIdGenerator`:实现 `IdentifierGenerator`,持久化时调用 `SnowflakeHelper.next()` ### 部分更新 Fenix `saveOrUpdateByNotNullProperties()`: - 自动判断 INSERT/UPDATE - 仅更新非 null 字段 ### 命名策略 `PhysicalNamingStrategySnakeCaseImpl`:camelCase → snake_case ### 注解处理器 执行顺序:lombok → hibernate-jpamodelgen → querydsl-apt → mapstruct-processor 生成:getter/setter、JPA 元模型(_Entity)、QueryDSL Q 类(QEntity)、MapStruct Mapper ## 工具类 ### DatabaseHelper ```java // 生成 DDL generateDDL(entityPackages, ddlFilePath, dialect, jdbc, username, password, driver) // 生成脚手架 generateBasicFiles(entityPackages, projectRootPackage, projectRootPath, override) ``` ### SnowflakeHelper ```java Long id = SnowflakeHelper.next(); ``` ## 扩展指南 ### 软删除 1. 创建 `SoftDeleteEntity extends SimpleEntity`,添加 `deleted` 字段 2. 重写 `commonPredicates()` 返回 `deleted = false` 条件 3. 覆盖 `remove()` 改为更新 `deleted` 字段 ### 多租户 1. 创建 `TenantEntity extends SimpleEntity`,添加 `tenantId` 字段 2. 重写 `commonPredicates()` 添加租户过滤 3. ThreadLocal 或 Spring Security 存储当前租户 ### 审计字段 在 `SimpleEntity` 添加 `createdBy`, `modifiedBy`,配合 Spring Security 获取当前用户 ### 自定义查询操作符 1. `Query.Queryable` 添加字段 2. `QueryParser` 添加抽象方法 3. `JpaQueryParser` 实现转换为 Predicate ## 测试 - H2 内存数据库 - `@DataJpaTest` 测试 Repository - `@WebMvcTest` 测试 Controller - 测试用例:`src/test/java/.../integration/` ## 依赖 核心:spring-boot-starter-data-jpa, fenix-spring-boot-starter:4.0.0, querydsl-jpa:7.1, mapstruct:1.6.3 传递:spring-boot-service-template-common ## 注意事项 - 事务:写操作 `@Transactional(rollbackFor = Throwable.class)`,读操作 `@Transactional(readOnly = true)` - 异常:不使用全局处理器,直接抛出 - 性能:批量操作使用批量方法 - 线程安全:GlobalResponse 用 record 保证不可变,SnowflakeHelper 用原子变量