5.9 KiB
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
@NoRepositoryBean
public interface SimpleRepository<E> extends
FenixJpaRepository<E, Long>, // CRUD + Fenix
FenixJpaSpecificationExecutor<E>, // Specification
ListQueryByExampleExecutor<E>, // Example
ListQuerydslPredicateExecutor<E> {} // QueryDSL
核心能力:
saveOrUpdateByNotNullProperties()- 部分字段更新- Specification - 动态条件查询
- QueryDSL - 类型安全查询
Service 接口组合
SaveService<ENTITY> // save(entity), save(entities)
QueryService<ENTITY> // detail(id), list(), list(query), count()
RemoveService<ENTITY> // remove(id), remove(ids)
SimpleService<ENTITY> extends SaveService, QueryService, RemoveService
SimpleServiceSupport 实现:
- 保存:Fenix
saveOrUpdateByNotNullProperties() - 查询:JPA Criteria + Specification
- 删除:
deleteBatchByIds() - 扩展点:重写
commonPredicates()添加全局过滤条件
Controller 接口组合
SaveController<SAVE_ITEM> // POST /save
QueryController<LIST_ITEM, DETAIL_ITEM> // GET/POST /list, GET /detail/{id}
RemoveController // GET /remove/{id}
SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM>
SimpleControllerSupport 实现:
- 调用 Service 方法
- 通过 Mapper 转换 DTO ↔ Entity
- 封装 GlobalResponse
- 扩展点:实现
saveItemMapper(),listItemMapper(),detailItemMapper()
查询条件
Query 结构:Query(query: Queryable, sort: List<Sortable>, 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)
响应格式
GlobalResponse<T>(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
// 生成 DDL
generateDDL(entityPackages, ddlFilePath, dialect, jdbc, username, password, driver)
// 生成脚手架
generateBasicFiles(entityPackages, projectRootPackage, projectRootPath, override)
SnowflakeHelper
Long id = SnowflakeHelper.next();
扩展指南
软删除
- 创建
SoftDeleteEntity extends SimpleEntity,添加deleted字段 - 重写
commonPredicates()返回deleted = false条件 - 覆盖
remove()改为更新deleted字段
多租户
- 创建
TenantEntity extends SimpleEntity,添加tenantId字段 - 重写
commonPredicates()添加租户过滤 - ThreadLocal 或 Spring Security 存储当前租户
审计字段
在 SimpleEntity 添加 createdBy, modifiedBy,配合 Spring Security 获取当前用户
自定义查询操作符
Query.Queryable添加字段QueryParser添加抽象方法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 用原子变量