mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 19:12:10 +08:00
feat(spec): Add CRUD services and repository specifications
- Added the CrudRepositorySpec API to define CRUD operations and normalized queries - Implement the CrudServiceImplSpec class to provide a generic implementation of CRUD services - Define the CrudServiceSpec interface to standardize the operation of the CRUD service - Add .gitattributes and .gitignore files to configure the code style and ignore files - Create a build.gradle.kts file and add project dependencies
This commit is contained in:
parent
1fa28e4c57
commit
b4cfc9865c
3
forgeboot-webmvc/spec/.gitattributes
vendored
Normal file
3
forgeboot-webmvc/spec/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/gradlew text eol=lf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
*.jar binary
|
||||||
40
forgeboot-webmvc/spec/.gitignore
vendored
Normal file
40
forgeboot-webmvc/spec/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
HELP.md
|
||||||
|
.gradle
|
||||||
|
build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Kotlin ###
|
||||||
|
.kotlin
|
||||||
6
forgeboot-webmvc/spec/build.gradle.kts
Normal file
6
forgeboot-webmvc/spec/build.gradle.kts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly(libs.springBootStarter.jpa)
|
||||||
|
compileOnly(libs.org.mapstruct)
|
||||||
|
implementation(project(Modules.Webmvc.DTO))
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.gewuyou.forgeboot.webmvc.spec.repository
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor
|
||||||
|
|
||||||
|
/**
|
||||||
|
*CRUD 存储库规范
|
||||||
|
*
|
||||||
|
* @since 2025-05-29 20:39:11
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
interface CrudRepositorySpec<Entity, Id>: JpaRepository<Entity, Id>, JpaSpecificationExecutor<Entity>
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
package com.gewuyou.forgeboot.webmvc.spec.service
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.PageResult
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.request.PageQueryReq
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRUD 服务规范
|
||||||
|
*
|
||||||
|
* 定义了对实体进行基本操作的服务接口,包括增删查改和分页查询等功能
|
||||||
|
*
|
||||||
|
* @param Entity 实体类型
|
||||||
|
* @param Id 实体标识符类型
|
||||||
|
* @param Filter 查询过滤器类型
|
||||||
|
* @since 2025-05-29 20:18:22
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
interface CrudServiceSpec<Entity: Any, Id: Any, Filter: Any> {
|
||||||
|
/**
|
||||||
|
* 根据ID获取实体
|
||||||
|
*
|
||||||
|
* @param id 实体的唯一标识符
|
||||||
|
* @return 返回实体,如果不存在则返回null
|
||||||
|
*/
|
||||||
|
fun findById(id: Id): Entity?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有实体列表
|
||||||
|
*
|
||||||
|
* @return 返回实体列表
|
||||||
|
*/
|
||||||
|
fun list(): List<Entity>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存一个实体
|
||||||
|
*
|
||||||
|
* @param entity 要保存的实体
|
||||||
|
* @return 返回保存后的实体
|
||||||
|
*/
|
||||||
|
fun save(entity: Entity): Entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新一个实体
|
||||||
|
*
|
||||||
|
* @param entity 要更新的实体
|
||||||
|
* @return 返回更新后的实体
|
||||||
|
*/
|
||||||
|
fun update(entity: Entity): Entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个实体
|
||||||
|
*
|
||||||
|
* @param id 要删除的实体的ID
|
||||||
|
*/
|
||||||
|
fun delete(id: Id)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除实体
|
||||||
|
*
|
||||||
|
* @param ids 要删除的实体的ID列表
|
||||||
|
*/
|
||||||
|
fun delete(ids: List<Id>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个实体
|
||||||
|
*
|
||||||
|
* @param entity 要删除的实体
|
||||||
|
*/
|
||||||
|
fun delete(entity: Entity)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除实体
|
||||||
|
*
|
||||||
|
* @param entities 要删除的实体列表
|
||||||
|
*/
|
||||||
|
fun delete(entities: List<Entity>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID检查实体是否存在
|
||||||
|
*
|
||||||
|
* @param id 实体的ID
|
||||||
|
* @return 如果实体存在返回true,否则返回false
|
||||||
|
*/
|
||||||
|
fun existsById(id: Id): Boolean
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存实体
|
||||||
|
*
|
||||||
|
* @param entities 要保存的实体列表
|
||||||
|
* @return 返回保存后的实体列表
|
||||||
|
*/
|
||||||
|
fun saveAll(entities: List<Entity>): List<Entity>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询并映射结果
|
||||||
|
*
|
||||||
|
* @param query 分页查询请求,包含查询参数和分页信息
|
||||||
|
* @return 返回映射后的分页结果
|
||||||
|
*/
|
||||||
|
fun page(query: PageQueryReq<Filter>): PageResult<Entity>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询并使用给定函数映射结果
|
||||||
|
*
|
||||||
|
* @param query 分页查询请求,包含查询参数和分页信息
|
||||||
|
* @param mapping 映射函数,用于将实体映射为其他类型
|
||||||
|
* @param <V> 映射后的类型
|
||||||
|
* @return 返回映射后的分页结果
|
||||||
|
*/
|
||||||
|
fun <V> pageMapped(query: PageQueryReq<Filter>, mapping: (Entity) -> V): PageResult<V>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据过滤条件统计实体数量
|
||||||
|
*
|
||||||
|
* @param filter 查询过滤器
|
||||||
|
* @return 返回满足条件的实体数量
|
||||||
|
*/
|
||||||
|
fun count(filter: Filter): Long
|
||||||
|
}
|
||||||
@ -0,0 +1,191 @@
|
|||||||
|
package com.gewuyou.forgeboot.webmvc.spec.service.impl
|
||||||
|
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.PageResult
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.extension.map
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.extension.toPageResult
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.extension.toPageable
|
||||||
|
import com.gewuyou.forgeboot.webmvc.dto.request.PageQueryReq
|
||||||
|
import com.gewuyou.forgeboot.webmvc.spec.repository.CrudRepositorySpec
|
||||||
|
import com.gewuyou.forgeboot.webmvc.spec.service.CrudServiceSpec
|
||||||
|
import org.springframework.data.jpa.domain.Specification
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRUD 服务实现的抽象类,提供通用的数据访问操作。
|
||||||
|
*
|
||||||
|
* @since 2025-05-29 20:37:27
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
abstract class CrudServiceImplSpec<Entity : Any, Id : Any, Filter : Any>(
|
||||||
|
private val repository: CrudRepositorySpec<Entity, Id>,
|
||||||
|
) : CrudServiceSpec<Entity, Id, Filter> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据实体的唯一标识符查找实体对象。
|
||||||
|
*
|
||||||
|
* @param id 实体的唯一标识符
|
||||||
|
* @return 如果存在则返回对应的实体对象,否则返回 null
|
||||||
|
*/
|
||||||
|
override fun findById(id: Id): Entity? {
|
||||||
|
return repository.findById(id).orElse(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行分页查询并返回原始实体的分页结果。
|
||||||
|
*
|
||||||
|
* @param query 分页查询请求,包含过滤条件和分页信息
|
||||||
|
* @return 返回实体类型的分页结果
|
||||||
|
*/
|
||||||
|
override fun page(query: PageQueryReq<Filter>): PageResult<Entity> {
|
||||||
|
return repository
|
||||||
|
.findAll(
|
||||||
|
buildSpecification(query),
|
||||||
|
query.toPageable()
|
||||||
|
)
|
||||||
|
.toPageResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 JPA Specification 查询条件。
|
||||||
|
*
|
||||||
|
* @param query 包含过滤条件的分页请求
|
||||||
|
* @return 返回构建好的 Specification 查询条件
|
||||||
|
*/
|
||||||
|
protected abstract fun buildSpecification(query: PageQueryReq<Filter>): Specification<Entity>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有实体列表。
|
||||||
|
*
|
||||||
|
* @return 返回实体列表
|
||||||
|
*/
|
||||||
|
override fun list(): List<Entity> {
|
||||||
|
return repository.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存一个实体对象。
|
||||||
|
*
|
||||||
|
* @param entity 要保存的实体对象
|
||||||
|
* @return 返回保存后的实体对象
|
||||||
|
*/
|
||||||
|
override fun save(entity: Entity): Entity {
|
||||||
|
return repository.save(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据实体 ID 删除指定的实体。
|
||||||
|
*
|
||||||
|
* @param id 要删除的实体的唯一标识符
|
||||||
|
*/
|
||||||
|
override fun delete(id: Id) {
|
||||||
|
repository.deleteById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除多个实体(根据 ID 列表)。
|
||||||
|
*
|
||||||
|
* @param ids 要删除的实体 ID 列表
|
||||||
|
*/
|
||||||
|
override fun delete(ids: List<Id>) {
|
||||||
|
repository.deleteAllById(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定的单个实体。
|
||||||
|
*
|
||||||
|
* @param entity 要删除的实体对象
|
||||||
|
*/
|
||||||
|
override fun delete(entity: Entity) {
|
||||||
|
repository.delete(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除多个实体。
|
||||||
|
*
|
||||||
|
* @param entities 要删除的实体列表
|
||||||
|
*/
|
||||||
|
override fun delete(entities: List<Entity>) {
|
||||||
|
repository.deleteAll(entities)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将更新实体的非 null 字段合并到已有持久化对象上。
|
||||||
|
* 此方法通常由 MapStruct 等映射工具实现。
|
||||||
|
*
|
||||||
|
* @param entity 包含更新数据的实体对象
|
||||||
|
* @param existing 数据库中已存在的实体对象
|
||||||
|
* @return 返回合并后的实体对象
|
||||||
|
*/
|
||||||
|
protected abstract fun merge(entity: Entity, existing: Entity): Entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取实体对象中的唯一标识符。
|
||||||
|
*
|
||||||
|
* @param entity 实体对象
|
||||||
|
* @return 返回实体的唯一标识符
|
||||||
|
*/
|
||||||
|
protected abstract fun extractId(entity: Entity): Id
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新一个实体对象。
|
||||||
|
*
|
||||||
|
* @param entity 包含更新数据的实体对象
|
||||||
|
* @return 返回更新后的实体对象
|
||||||
|
*/
|
||||||
|
override fun update(entity: Entity): Entity {
|
||||||
|
val existing = repository.findById(extractId(entity))
|
||||||
|
.orElseThrow { IllegalArgumentException("Entity not found") }
|
||||||
|
|
||||||
|
val merged = merge(entity, existing)
|
||||||
|
return repository.save(merged)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行分页查询并将结果使用给定的映射函数转换为其他类型。
|
||||||
|
*
|
||||||
|
* @param query 分页查询请求,包含查询参数和分页信息
|
||||||
|
* @param mapping 映射函数,用于将实体映射为其他类型
|
||||||
|
* @param <V> 映射后的目标类型
|
||||||
|
* @return 返回映射后的分页结果
|
||||||
|
*/
|
||||||
|
override fun <V> pageMapped(
|
||||||
|
query: PageQueryReq<Filter>,
|
||||||
|
mapping: (Entity) -> V,
|
||||||
|
): PageResult<V> {
|
||||||
|
val page = repository.findAll(
|
||||||
|
buildSpecification(query),
|
||||||
|
query.toPageable()
|
||||||
|
)
|
||||||
|
return page.toPageResult().map(mapping)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据给定的过滤条件统计实体数量。
|
||||||
|
*
|
||||||
|
* @param filter 查询过滤器
|
||||||
|
* @return 返回满足条件的实体数量
|
||||||
|
*/
|
||||||
|
override fun count(filter: Filter): Long {
|
||||||
|
return repository.count(buildSpecification(PageQueryReq<Filter>().apply { this.filter = filter }))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查具有指定 ID 的实体是否存在。
|
||||||
|
*
|
||||||
|
* @param id 实体的唯一标识符
|
||||||
|
* @return 如果实体存在返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
override fun existsById(id: Id): Boolean {
|
||||||
|
return repository.existsById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存多个实体对象。
|
||||||
|
*
|
||||||
|
* @param entities 要保存的实体列表
|
||||||
|
* @return 返回保存后的实体列表
|
||||||
|
*/
|
||||||
|
override fun saveAll(entities: List<Entity>): List<Entity> {
|
||||||
|
return repository.saveAll(entities)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,7 +30,8 @@ include(
|
|||||||
":forgeboot-webmvc:logger",
|
":forgeboot-webmvc:logger",
|
||||||
":forgeboot-webmvc:exception",
|
":forgeboot-webmvc:exception",
|
||||||
":forgeboot-webmvc:dto",
|
":forgeboot-webmvc:dto",
|
||||||
":forgeboot-webmvc:validation"
|
":forgeboot-webmvc:validation",
|
||||||
|
":forgeboot-webmvc:spec"
|
||||||
)
|
)
|
||||||
project(":forgeboot-webmvc").name = "forgeboot-webmvc-spring-boot-starter"
|
project(":forgeboot-webmvc").name = "forgeboot-webmvc-spring-boot-starter"
|
||||||
project(":forgeboot-webmvc:version").name = "forgeboot-webmvc-version-spring-boot-starter"
|
project(":forgeboot-webmvc:version").name = "forgeboot-webmvc-version-spring-boot-starter"
|
||||||
@ -38,6 +39,7 @@ project(":forgeboot-webmvc:logger").name = "forgeboot-webmvc-logger-spring-boot-
|
|||||||
project(":forgeboot-webmvc:exception").name = "forgeboot-webmvc-exception-spring-boot-starter"
|
project(":forgeboot-webmvc:exception").name = "forgeboot-webmvc-exception-spring-boot-starter"
|
||||||
project(":forgeboot-webmvc:dto").name = "forgeboot-webmvc-dto"
|
project(":forgeboot-webmvc:dto").name = "forgeboot-webmvc-dto"
|
||||||
project(":forgeboot-webmvc:validation").name = "forgeboot-validation"
|
project(":forgeboot-webmvc:validation").name = "forgeboot-validation"
|
||||||
|
project(":forgeboot-webmvc:spec").name = "forgeboot-webmvc-spec"
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region module core
|
//region module core
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user