From 307908b923f50388a56f62835ca738d4add1ceea Mon Sep 17 00:00:00 2001 From: gewuyou Date: Fri, 25 Jul 2025 14:29:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(spec):=20=E9=87=8D=E6=9E=84=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E6=A8=A1=E5=9D=97=E4=BB=A5=E6=8F=90=E9=AB=98=E5=8F=AF?= =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E6=80=A7=E5=92=8C=E6=89=A9=E5=B1=95=E6=80=A7?= =?UTF-8?q?-=20=E9=87=8D=E6=96=B0=E7=BB=84=E7=BB=87=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=8C=E5=B0=86=E9=80=9A=E7=94=A8=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E7=A7=BB=E8=87=B3=20spec-core=20=E6=A8=A1=E5=9D=97=20?= =?UTF-8?q?-=20=E6=96=B0=E5=A2=9E=20QueryComponentExtensions=E3=80=81Sorta?= =?UTF-8?q?bleExtensions=20=E7=AD=89=E6=89=A9=E5=B1=95=E5=87=BD=E6=95=B0?= =?UTF-8?q?=20-=20=E9=87=8D=E6=9E=84=20JpaCrudServiceSpec=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E4=BD=BF=E5=85=B6=E7=BB=A7=E6=89=BF=E8=87=AA?= =?UTF-8?q?=E9=80=9A=E7=94=A8=E7=9A=84=20CrudServiceSpec=20-=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20JpaCrudServiceImplSpec=20=E6=8A=BD=E8=B1=A1?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=BD=AF=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=96=B9=E6=B3=95=20-=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20SimpleJpaCrudServiceImplSpec=20=E7=B1=BB=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E4=B8=8D=E6=94=AF=E6=8C=81=E8=BD=AF=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=9A=84=E7=AE=80=E5=8D=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- forgeboot-webmvc/spec-core/build.gradle.kts | 3 +- .../spec/core}/extension/PageExtensions.kt | 2 +- .../core}/extension/PageResultExtensions.kt | 2 +- .../extension/QueryComponentExtensions.kt | 30 ++++ .../core/extension/SortDirectionExtensions.kt | 12 ++ .../spec/core/extension/SortableExtensions.kt | 37 +++++ .../request/AbstractDateStatusPageRequest.kt | 1 - .../spec/core/service/CrudServiceSpec.kt | 133 ++++++++++++++++++ .../jpa/extension/JpaPredicateExtensions.kt | 69 +-------- .../spec/jpa/service/JpaCrudServiceSpec.kt | 101 +------------ .../service/impl/JpaCrudServiceImplSpec.kt | 80 ++++++++++- .../impl/SimpleJpaCrudServiceImplSpec.kt | 47 +++++++ 12 files changed, 348 insertions(+), 169 deletions(-) rename forgeboot-webmvc/{spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa => spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core}/extension/PageExtensions.kt (94%) rename forgeboot-webmvc/{spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa => spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core}/extension/PageResultExtensions.kt (94%) create mode 100644 forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/QueryComponentExtensions.kt create mode 100644 forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortDirectionExtensions.kt create mode 100644 forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortableExtensions.kt create mode 100644 forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/service/CrudServiceSpec.kt create mode 100644 forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/SimpleJpaCrudServiceImplSpec.kt diff --git a/forgeboot-webmvc/spec-core/build.gradle.kts b/forgeboot-webmvc/spec-core/build.gradle.kts index 2e3ca6a..b11e575 100644 --- a/forgeboot-webmvc/spec-core/build.gradle.kts +++ b/forgeboot-webmvc/spec-core/build.gradle.kts @@ -1,3 +1,4 @@ dependencies { - + api(project(Modules.Webmvc.DTO)) + compileOnly(libs.springFramework.data.commons) } diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageExtensions.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageExtensions.kt similarity index 94% rename from forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageExtensions.kt rename to forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageExtensions.kt index 3ce1385..84019dd 100644 --- a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageExtensions.kt +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageExtensions.kt @@ -1,4 +1,4 @@ -package com.gewuyou.webmvc.spec.jpa.extension +package com.gewuyou.webmvc.spec.core.extension import com.gewuyou.forgeboot.webmvc.dto.PageResult import org.springframework.data.domain.Page diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageResultExtensions.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageResultExtensions.kt similarity index 94% rename from forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageResultExtensions.kt rename to forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageResultExtensions.kt index 223a0cc..38fe74f 100644 --- a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/PageResultExtensions.kt +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/PageResultExtensions.kt @@ -1,4 +1,4 @@ -package com.gewuyou.webmvc.spec.jpa.extension +package com.gewuyou.webmvc.spec.core.extension import com.gewuyou.forgeboot.webmvc.dto.PageResult diff --git a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/QueryComponentExtensions.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/QueryComponentExtensions.kt new file mode 100644 index 0000000..5581136 --- /dev/null +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/QueryComponentExtensions.kt @@ -0,0 +1,30 @@ +package com.gewuyou.webmvc.spec.core.extension + +import com.gewuyou.webmvc.spec.core.page.Pageable +import com.gewuyou.webmvc.spec.core.page.QueryComponent +import com.gewuyou.webmvc.spec.core.page.Sortable +import org.springframework.data.domain.PageRequest +import org.springframework.data.domain.Sort + +/** + * 将 QueryComponent 转换为 Spring Data 的 PageRequest 对象 + * + * + * @return PageRequest 分页请求对象,包含分页和排序信息 + * + * 重要逻辑说明: + * 1. currentPage 从 1 开始计数,转换为 Spring Data 从 0 开始的页码 + * 2. pageSize 保持不变,直接用于分页请求 + * 3. 如果对象实现了 Sortable 接口,则使用其排序条件;否则使用未排序状态 + * 4. 如果对象未实现 Pageable 接口,则使用默认分页参数(第一页,每页10条) + */ +fun QueryComponent.toPageRequest(): PageRequest { + val pageable = this as? Pageable + val sortable = this as? Sortable + // 默认分页参数 + val page = pageable?.let { (it.currentPage - 1).coerceAtLeast(0) } ?: 0 + val size = pageable?.pageSize ?: 10 + // 排序规则 + val sort = sortable?.let { Sort.by(it.toSortOrders()) } ?: Sort.unsorted() + return PageRequest.of(page, size, sort) +} \ No newline at end of file diff --git a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortDirectionExtensions.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortDirectionExtensions.kt new file mode 100644 index 0000000..7848eb8 --- /dev/null +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortDirectionExtensions.kt @@ -0,0 +1,12 @@ +package com.gewuyou.webmvc.spec.core.extension + +import com.gewuyou.webmvc.spec.core.enums.SortDirection +import org.springframework.data.domain.Sort + +/** + * 将自定义的排序方向枚举转换为 Spring Data的排序方向 + * + * @return 对应的 Spring Data Sort.Direction 枚举值 + */ +fun SortDirection.toSpringDirection(): Sort.Direction = + if (this == SortDirection.DESC) Sort.Direction.DESC else Sort.Direction.ASC diff --git a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortableExtensions.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortableExtensions.kt new file mode 100644 index 0000000..7516b3e --- /dev/null +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/extension/SortableExtensions.kt @@ -0,0 +1,37 @@ +package com.gewuyou.webmvc.spec.core.extension + +import com.gewuyou.webmvc.spec.core.page.Sortable +import org.springframework.data.domain.Sort +import kotlin.collections.map + +/** + * 将当前排序配置转换为可用于 Spring Data Pageable 的排序条件列表 + * + * @param defaultSort 当没有其他排序条件时使用的默认排序,默认为按 createdAt 降序 + * @return 适用于 Pageable 的排序条件列表 + * + * 处理逻辑优先级: + * 1. 如果存在多个排序条件,使用 sortConditions 构建排序列表 + * 2. 如果指定了单一排序字段,使用 sortBy 和 sortDirection 构建排序条件 + * 3. 如果没有指定任何排序条件,使用默认排序 + */ +fun Sortable.toSortOrders(defaultSort: Sort.Order = Sort.Order.desc("createdAt")): List { + return when { + sortConditions.isNotEmpty() -> { + // 使用 map 将每个 SortCondition 转换为 Spring 的 Sort.Order 对象 + sortConditions.map { + Sort.Order( + it.direction.toSpringDirection(), + it.property + ) + } + } + + sortBy.isNotBlank() -> { + // 当存在单一排序字段时,创建对应的排序条件列表 + listOf(Sort.Order(sortDirection.toSpringDirection(), sortBy)) + } + + else -> listOf(defaultSort) + } +} diff --git a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/request/AbstractDateStatusPageRequest.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/request/AbstractDateStatusPageRequest.kt index 45a8ec3..c07b331 100644 --- a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/request/AbstractDateStatusPageRequest.kt +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/request/AbstractDateStatusPageRequest.kt @@ -11,7 +11,6 @@ import com.gewuyou.webmvc.spec.core.page.StatusFilterable * * @property currentPage 当前页码,从1开始计数的分页参数 * @property pageSize 每页记录数量,控制分页大小 - * @property statusConditions 状态条件映射,键值对形式表示的状态过滤条件 * * @since 2025-07-19 09:15:12 * @author gewuyou diff --git a/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/service/CrudServiceSpec.kt b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/service/CrudServiceSpec.kt new file mode 100644 index 0000000..b791204 --- /dev/null +++ b/forgeboot-webmvc/spec-core/src/main/kotlin/com/gewuyou/webmvc/spec/core/service/CrudServiceSpec.kt @@ -0,0 +1,133 @@ +package com.gewuyou.webmvc.spec.core.service + +/** + *CRUD服务规范 + * + * @since 2025-07-25 11:12:32 + * @author gewuyou + */ +interface CrudServiceSpec { + /** + * 根据ID获取实体 + * + * @param id 实体的唯一标识符 + * @return 返回实体,如果不存在则返回null + */ + fun findById(id: Id): Entity? + + /** + * 获取所有实体列表 + * + * @return 返回实体列表 + */ + fun list(): List + + /** + * 保存一个实体 + * + * @param entity 要保存的实体 + * @return 返回保存后的实体 + */ + fun save(entity: Entity): Entity + + /** + * 更新一个实体 + * + * @param entity 要更新的实体 + * @return 返回更新后的实体 + */ + fun update(entity: Entity): Entity + + /** + * 删除一个实体 + * + * @param id 要删除的实体的ID + */ + fun deleteById(id: Id) + + /** + * 批量删除实体 + * + * @param ids 要删除的实体的ID列表 + */ + fun deleteByIds(ids: List) + + /** + * 删除一个实体 + * + * @param entity 要删除的实体 + */ + fun deleteByOne(entity: Entity) + + /** + * 批量删除实体 + * + * @param entities 要删除的实体列表 + */ + fun deleteByAll(entities: List) + + /** + * 软删除 + * + * 本函数用于标记实体为删除状态,而不是真正从数据库中移除 + * 这种方法可以保留历史数据,同时避免数据泄露 + * + * @param id 实体的唯一标识符 + */ + fun softDelete(id: Id) + + /** + * 批量软删除 + * + * @param ids 要软删除的实体ID列表 + */ + fun softDeleteByIds(ids: List) + + /** + * 取消软删除(恢复已删除实体) + * + * @param id 要恢复的实体ID + */ + fun restore(id: Id) + + /** + * 批量取消软删除 + * + * @param ids 要恢复的实体ID列表 + */ + fun restoreByIds(ids: List) + + /** + * 判断实体是否已被软删除 + * + * @param id 实体ID + * @return 如果是软删除状态返回 true,否则返回 false + */ + fun isSoftDeleted(id: Id): Boolean + + /** + * 根据ID检查实体是否存在 + * + * @param id 实体的ID + * @return 如果实体存在返回true,否则返回false + */ + fun existsById(id: Id): Boolean + + + /** + * 批量保存实体 + * + * @param entities 要保存的实体列表 + * @return 返回保存后的实体列表 + */ + fun saveAll(entities: List): List + + + /** + * 查询记录总数 + * + * + * @return 返回记录总数 + */ + fun count(): Long +} \ No newline at end of file diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/JpaPredicateExtensions.kt b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/JpaPredicateExtensions.kt index dd0459f..307f179 100644 --- a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/JpaPredicateExtensions.kt +++ b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/extension/JpaPredicateExtensions.kt @@ -1,64 +1,18 @@ package com.gewuyou.webmvc.spec.jpa.extension -import com.gewuyou.webmvc.spec.core.enums.SortDirection -import com.gewuyou.webmvc.spec.core.page.DateRangeFilterable -import com.gewuyou.webmvc.spec.core.page.KeywordSearchable -import com.gewuyou.webmvc.spec.core.page.Pageable -import com.gewuyou.webmvc.spec.core.page.QueryComponent -import com.gewuyou.webmvc.spec.core.page.Sortable +import com.gewuyou.webmvc.spec.core.extension.toPageRequest +import com.gewuyou.webmvc.spec.core.page.* import com.gewuyou.webmvc.spec.jpa.page.JpaFilterable import com.gewuyou.webmvc.spec.jpa.page.JpaStatusFilterable import jakarta.persistence.criteria.CriteriaBuilder import jakarta.persistence.criteria.Predicate import jakarta.persistence.criteria.Root - import org.springframework.data.domain.PageRequest -import org.springframework.data.domain.Sort import org.springframework.data.jpa.domain.Specification import java.time.Instant -/** - * 将自定义的排序方向枚举转换为 Spring Data JPA 的排序方向 - * - * @return 对应的 Spring Data Sort.Direction 枚举值 - */ -fun SortDirection.toSpringDirection(): Sort.Direction = - if (this == SortDirection.DESC) Sort.Direction.DESC else Sort.Direction.ASC - -/** - * 将当前排序配置转换为可用于 Spring Data Pageable 的排序条件列表 - * - * @param defaultSort 当没有其他排序条件时使用的默认排序,默认为按 createdAt 降序 - * @return 适用于 Pageable 的排序条件列表 - * - * 处理逻辑优先级: - * 1. 如果存在多个排序条件,使用 sortConditions 构建排序列表 - * 2. 如果指定了单一排序字段,使用 sortBy 和 sortDirection 构建排序条件 - * 3. 如果没有指定任何排序条件,使用默认排序 - */ -fun Sortable.toSortOrders(defaultSort: Sort.Order = Sort.Order.desc("createdAt")): List { - return when { - sortConditions.isNotEmpty() -> { - // 使用 map 将每个 SortCondition 转换为 Spring 的 Sort.Order 对象 - sortConditions.map { - Sort.Order( - it.direction.toSpringDirection(), - it.property - ) - } - } - - sortBy.isNotBlank() -> { - // 当存在单一排序字段时,创建对应的排序条件列表 - listOf(Sort.Order(sortDirection.toSpringDirection(), sortBy)) - } - - else -> listOf(defaultSort) - } -} - /** * 构建关键字搜索对应的 JPA Predicate 条件列表 * @@ -179,21 +133,6 @@ fun QueryComponent.toSpecification(): Specification { * @return 返回一个 Pair,包含以下两个元素: * - Specification:JPA 查询条件规范 * - PageRequest:包含分页和排序信息的请求对象 - * - * 重要逻辑说明: - * 1. currentPage 从 1 开始计数,转换为 Spring Data 从 0 开始的页码 - * 2. pageSize 保持不变,直接用于分页请求 - * 3. 如果对象实现了 Sortable 接口,则使用其排序条件;否则使用未排序状态 - * 4. 如果对象未实现 Pageable 接口,则使用默认分页参数(第一页,每页10条) */ -fun QueryComponent.toJpaQuery(): Pair, PageRequest> { - val specification = this.toSpecification() - val pageable = this as? Pageable - val sortable = this as? Sortable - // 默认分页参数 - val page = pageable?.let { (it.currentPage - 1).coerceAtLeast(0) } ?: 0 - val size = pageable?.pageSize ?: 10 - // 排序规则 - val sort = sortable?.let { Sort.by(it.toSortOrders()) } ?: Sort.unsorted() - return specification to PageRequest.of(page, size, sort) -} \ No newline at end of file +fun QueryComponent.toJpaQuery(): Pair, PageRequest> = + this.toSpecification() to this.toPageRequest() \ No newline at end of file diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/JpaCrudServiceSpec.kt b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/JpaCrudServiceSpec.kt index b85a5ce..7af6a8e 100644 --- a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/JpaCrudServiceSpec.kt +++ b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/JpaCrudServiceSpec.kt @@ -2,106 +2,15 @@ package com.gewuyou.webmvc.spec.jpa.service import com.gewuyou.forgeboot.webmvc.dto.PageResult import com.gewuyou.webmvc.spec.core.page.QueryComponent - +import com.gewuyou.webmvc.spec.core.service.CrudServiceSpec /** - * Jpa CRUD 服务规范 + *JPA Crud服务规范 * - * 定义了对实体进行基本操作的服务接口,包括增删查改和分页查询等功能 - * - * @param Entity 实体类型 - * @param Id 实体标识符类型 - * @since 2025-05-29 20:18:22 + * @since 2025-07-25 12:41:39 * @author gewuyou */ -interface JpaCrudServiceSpec { - /** - * 根据ID获取实体 - * - * @param id 实体的唯一标识符 - * @return 返回实体,如果不存在则返回null - */ - fun findById(id: Id): Entity? - - /** - * 获取所有实体列表 - * - * @return 返回实体列表 - */ - fun list(): List - - /** - * 保存一个实体 - * - * @param entity 要保存的实体 - * @return 返回保存后的实体 - */ - fun save(entity: Entity): Entity - - /** - * 更新一个实体 - * - * @param entity 要更新的实体 - * @return 返回更新后的实体 - */ - fun update(entity: Entity): Entity - - /** - * 删除一个实体 - * - * @param id 要删除的实体的ID - */ - fun deleteById(id: Id) - - /** - * 批量删除实体 - * - * @param ids 要删除的实体的ID列表 - */ - fun deleteByIds(ids: List) - - /** - * 删除一个实体 - * - * @param entity 要删除的实体 - */ - fun deleteByOne(entity: Entity) - - /** - * 批量删除实体 - * - * @param entities 要删除的实体列表 - */ - fun deleteByAll(entities: List) - - /** - * 软删除 - * - * 本函数用于标记实体为删除状态,而不是真正从数据库中移除 - * 这种方法可以保留历史数据,同时避免数据泄露 - * - * @param id 实体的唯一标识符 - */ - fun softDelete(id: Id) - - /** - * 根据ID检查实体是否存在 - * - * @param id 实体的ID - * @return 如果实体存在返回true,否则返回false - */ - fun existsById(id: Id): Boolean - - - /** - * 批量保存实体 - * - * @param entities 要保存的实体列表 - * @return 返回保存后的实体列表 - */ - fun saveAll(entities: List): List - - +interface JpaCrudServiceSpec: CrudServiceSpec { /** * 分页查询实体列表 * @@ -136,4 +45,4 @@ interface JpaCrudServiceSpec { * @return 返回符合条件的记录总数 */ fun count(query: QueryComponent): Long -} +} \ No newline at end of file diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/JpaCrudServiceImplSpec.kt b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/JpaCrudServiceImplSpec.kt index 260b00d..5aa4d6e 100644 --- a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/JpaCrudServiceImplSpec.kt +++ b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/JpaCrudServiceImplSpec.kt @@ -1,16 +1,14 @@ package com.gewuyou.webmvc.spec.jpa.service.impl import com.gewuyou.forgeboot.webmvc.dto.PageResult - +import com.gewuyou.webmvc.spec.core.extension.map +import com.gewuyou.webmvc.spec.core.extension.toPageResult import com.gewuyou.webmvc.spec.core.page.QueryComponent -import com.gewuyou.webmvc.spec.jpa.extension.map import com.gewuyou.webmvc.spec.jpa.extension.toJpaQuery -import com.gewuyou.webmvc.spec.jpa.extension.toPageResult import com.gewuyou.webmvc.spec.jpa.extension.toSpecification import com.gewuyou.webmvc.spec.jpa.repository.JpaCrudRepositorySpec import com.gewuyou.webmvc.spec.jpa.service.JpaCrudServiceSpec - /** * Jpa CRUD 服务实现的抽象类,提供通用的数据访问操作。 * @@ -195,6 +193,24 @@ abstract class JpaCrudServiceImplSpec( */ protected abstract fun setDeleted(entity: Entity) + /** + * 将实体标记为已恢复状态。 + * + * 此方法应在子类中实现,用于定义如何将实体从软删除状态恢复为正常状态(例如清除 deleted 字段或设置为 false)。 + * 该机制允许在不物理删除数据的情况下,灵活地控制记录的可见性与状态。 + * + * @param entity 实体对象,表示要恢复的实体 + */ + protected abstract fun setRestored(entity: Entity) + + /** + * 判断实体是否已被软删除 + * + * @param entity 实体对象,用于检查其删除状态 + * @return 如果实体已被标记为软删除状态返回 true,否则返回 false + */ + protected abstract fun isSoftDeleted(entity: Entity): Boolean + /** * 执行软删除操作。 * @@ -212,4 +228,60 @@ abstract class JpaCrudServiceImplSpec( update(it) } } + + /** + * 查询记录总数 + * + * + * @return 返回记录总数 + */ + override fun count(): Long { + return repository.count() + } + + /** + * 批量软删除 + * + * @param ids 要软删除的实体ID列表 + */ + override fun softDeleteByIds(ids: List) { + ids.forEach { + softDelete( it) + } + } + + /** + * 取消软删除(恢复已删除实体) + * + * @param id 要恢复的实体ID + */ + override fun restore(id: Id) { + val exist: Entity? = findById(id) + exist?.let { + setRestored(exist) + update(it) + } + } + + /** + * 批量取消软删除 + * + * @param ids 要恢复的实体ID列表 + */ + override fun restoreByIds(ids: List) { + ids.forEach { + restore(it) + } + } + + /** + * 判断实体是否已被软删除 + * + * @param id 实体ID + * @return 如果是软删除状态返回 true,否则返回 false + */ + override fun isSoftDeleted(id: Id): Boolean { + val entity = findById(id)?:return false + return isSoftDeleted(entity) + } } \ No newline at end of file diff --git a/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/SimpleJpaCrudServiceImplSpec.kt b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/SimpleJpaCrudServiceImplSpec.kt new file mode 100644 index 0000000..4206237 --- /dev/null +++ b/forgeboot-webmvc/spec-jpa/src/main/kotlin/com/gewuyou/webmvc/spec/jpa/service/impl/SimpleJpaCrudServiceImplSpec.kt @@ -0,0 +1,47 @@ +package com.gewuyou.webmvc.spec.jpa.service.impl + +import com.gewuyou.webmvc.spec.jpa.repository.JpaCrudRepositorySpec + +/** + *简单的JPA Crud服务实现规范,请注意该抽象实现类不实现软删除 + * + * @since 2025-07-25 14:24:19 + * @author gewuyou + */ +abstract class SimpleJpaCrudServiceImplSpec( + private val repository: JpaCrudRepositorySpec, +): JpaCrudServiceImplSpec(repository) { + /** + * 标记实体为软删除状态。 + * + * 此方法应在子类中实现,用于定义如何将实体标记为已删除(例如设置一个 deleted 字段)。 + * 软删除不会从数据库中物理移除记录,而是将其标记为已删除状态,以便保留历史数据。 + * + * @param entity 实体对象,表示要标记为删除状态的对象 + */ + override fun setDeleted(entity: Entity) { + // 不实现 + } + + /** + * 将实体标记为已恢复状态。 + * + * 此方法应在子类中实现,用于定义如何将实体从软删除状态恢复为正常状态(例如清除 deleted 字段或设置为 false)。 + * 该机制允许在不物理删除数据的情况下,灵活地控制记录的可见性与状态。 + * + * @param entity 实体对象,表示要恢复的实体 + */ + override fun setRestored(entity: Entity) { + // 不实现 + } + + /** + * 判断实体是否已被软删除 + * + * @param entity 实体对象,用于检查其删除状态 + * @return 如果实体已被标记为软删除状态返回 true,否则返回 false + */ + override fun isSoftDeleted(entity: Entity): Boolean { + return false + } +} \ No newline at end of file