1
0

refactor(common): 将包结构从 jpa 迁移至 common 并重构核心类

- 将所有控制器接口从 jpa 包迁移至 common 包
- 将 GlobalResponse、Query、Page 等核心类重构为 record 类型
- 移除 Lombok 依赖并简化代码结构
- 更新 SimpleService 接口以支持更通用的实体类型
- 调整 SimpleControllerSupport 和 SimpleServiceSupport 以适配新的 API
- 清理 web 模块的 pom.xml 中的冗余依赖和配置
This commit is contained in:
2026-01-06 14:24:51 +08:00
parent 2a374dc9c7
commit 142b57975b
13 changed files with 255 additions and 344 deletions

View File

@@ -1,4 +1,4 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
/** /**
* 详情控制器接口用于定义统一的获取实体详情的接口规范 * 详情控制器接口用于定义统一的获取实体详情的接口规范

View File

@@ -1,42 +1,23 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
import java.util.Map; import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter public record GlobalResponse<T>(
@Getter Integer status,
@ToString String message,
public class GlobalResponse<T> { T data
) {
private static final int SUCCESS_STATUS = 0; private static final int SUCCESS_STATUS = 0;
private static final int ERROR_STATUS = 500; private static final int ERROR_STATUS = 500;
private static final String SUCCESS_MESSAGE = "OK"; private static final String SUCCESS_MESSAGE = "OK";
private static final String ERROR_MESSAGE = "ERROR"; private static final String ERROR_MESSAGE = "ERROR";
private Integer status;
private String message;
private T data;
private GlobalResponse() {
this(SUCCESS_STATUS, SUCCESS_MESSAGE, null);
}
private GlobalResponse(Integer status, String message) {
this(status, message, null);
}
private GlobalResponse(Integer status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
public static GlobalResponse<Object> responseError() { public static GlobalResponse<Object> responseError() {
return responseError(ERROR_MESSAGE); return responseError(ERROR_MESSAGE);
} }
public static GlobalResponse<Object> responseError(String message) { public static GlobalResponse<Object> responseError(String message) {
return new GlobalResponse<>(ERROR_STATUS, message); return new GlobalResponse<>(ERROR_STATUS, message, null);
} }
public static GlobalResponse<Object> responseSuccess() { public static GlobalResponse<Object> responseSuccess() {

View File

@@ -1,4 +1,4 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
import java.util.Map; import java.util.Map;

View File

@@ -0,0 +1,133 @@
package com.lanyuanxiaoyao.service.template.common.controller;
import java.util.List;
import java.util.Map;
/**
* 查询条件封装类,用于构建复杂的查询条件
* 包含查询条件、排序条件和分页条件
*
* <p>前端传入的JSON格式示例:</p>
* <pre>
* {
* "query": {
* "equal": {
* "name": "张三"
* },
* "like": {
* "address": "%北京%"
* },
* "greatEqual": {
* "age": 18
* },
* "less": {
* "age": 60
* },
* "between": {
* "salary": {
* "start": 5000,
* "end": 10000
* }
* }
* },
* "sort": [
* {
* "column": "createTime",
* "direction": "DESC"
* }
* ],
* "page": {
* "index": 0,
* "size": 10
* }
* }
* </pre>
*
* <p>查询条件说明:</p>
* <ul>
* <li>nullEqual: 字段值为null的条件</li>
* <li>notNullEqual: 字段值不为null的条件</li>
* <li>empty: 字段值为空的条件</li>
* <li>notEmpty: 字段值不为空的条件</li>
* <li>equal: 字段值相等的条件</li>
* <li>notEqual: 字段值不相等的条件</li>
* <li>like: 字段值模糊匹配的条件</li>
* <li>notLike: 字段值不模糊匹配的条件</li>
* <li>great: 字段值大于的条件</li>
* <li>less: 字段值小于的条件</li>
* <li>greatEqual: 字段值大于等于的条件</li>
* <li>lessEqual: 字段值小于等于的条件</li>
* <li>in: 字段值在指定范围内的条件</li>
* <li>notIn: 字段值不在指定范围内的条件</li>
* <li>between: 字段值在指定区间内的条件</li>
* <li>notBetween: 字段值不在指定区间内的条件</li>
* </ul>
*/
public record Query(
Queryable query,
List<Sortable> sort,
Pageable page
) {
/**
* 可查询条件类,封装各种查询条件
*/
public record Queryable(
List<String> nullEqual,
List<String> notNullEqual,
List<String> empty,
List<String> notEmpty,
Map<String, Object> equal,
Map<String, Object> notEqual,
Map<String, String> like,
Map<String, String> notLike,
Map<String, String> contain,
Map<String, String> notContain,
Map<String, String> startWith,
Map<String, String> notStartWith,
Map<String, String> endWith,
Map<String, String> notEndWith,
Map<String, Object> great,
Map<String, Object> less,
Map<String, Object> greatEqual,
Map<String, Object> lessEqual,
Map<String, List<Object>> inside,
Map<String, List<Object>> notInside,
Map<String, Between> between,
Map<String, Between> notBetween
) {
/**
* 区间范围类,用于表示起始值和结束值
*/
public record Between(
Object start,
Object end
) {
}
}
public record Sortable(
String column,
Direction direction
) {
public enum Direction {
/**
* 升序排列
*/
ASC,
/**
* 降序排列
*/
DESC,
}
}
/**
* 可分页条件类,用于指定分页参数
*/
public record Pageable(
Integer index,
Integer size
) {
}
}

View File

@@ -1,4 +1,4 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
/** /**
* 删除控制器接口用于定义统一的删除实体对象的接口规范 * 删除控制器接口用于定义统一的删除实体对象的接口规范

View File

@@ -1,4 +1,4 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
/** /**
* 保存控制器接口用于定义统一的保存实体对象的接口规范 * 保存控制器接口用于定义统一的保存实体对象的接口规范

View File

@@ -1,4 +1,4 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.common.controller;
public interface SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> extends SaveController<SAVE_ITEM>, ListController<LIST_ITEM>, DetailController<DETAIL_ITEM>, RemoveController { public interface SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> extends SaveController<SAVE_ITEM>, ListController<LIST_ITEM>, DetailController<DETAIL_ITEM>, RemoveController {
} }

View File

@@ -0,0 +1,12 @@
package com.lanyuanxiaoyao.service.template.common.service;
import java.util.stream.Stream;
/**
* 分页
*
* @author lanyuanxiaoyao
* @version 20260106
*/
public record Page<ENTITY>(Stream<ENTITY> items, long total) {
}

View File

@@ -1,12 +1,10 @@
package com.lanyuanxiaoyao.service.template.jpa.service; package com.lanyuanxiaoyao.service.template.common.service;
import com.lanyuanxiaoyao.service.template.jpa.controller.Query; import com.lanyuanxiaoyao.service.template.common.controller.Query;
import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.springframework.data.domain.Page;
public interface SimpleService<ENTITY extends SimpleEntity> { public interface SimpleService<ENTITY> {
Long save(ENTITY entity) throws Exception; Long save(ENTITY entity) throws Exception;
void save(Iterable<ENTITY> entities) throws Exception; void save(Iterable<ENTITY> entities) throws Exception;

View File

@@ -1,247 +0,0 @@
package com.lanyuanxiaoyao.service.template.jpa.controller;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* 查询条件封装类,用于构建复杂的查询条件
* 包含查询条件、排序条件和分页条件
*
* <p>前端传入的JSON格式示例:</p>
* <pre>
* {
* "query": {
* "equal": {
* "name": "张三"
* },
* "like": {
* "address": "%北京%"
* },
* "greatEqual": {
* "age": 18
* },
* "less": {
* "age": 60
* },
* "between": {
* "salary": {
* "start": 5000,
* "end": 10000
* }
* }
* },
* "sort": [
* {
* "column": "createTime",
* "direction": "DESC"
* }
* ],
* "page": {
* "index": 0,
* "size": 10
* }
* }
* </pre>
*
* <p>查询条件说明:</p>
* <ul>
* <li>nullEqual: 字段值为null的条件</li>
* <li>notNullEqual: 字段值不为null的条件</li>
* <li>empty: 字段值为空的条件</li>
* <li>notEmpty: 字段值不为空的条件</li>
* <li>equal: 字段值相等的条件</li>
* <li>notEqual: 字段值不相等的条件</li>
* <li>like: 字段值模糊匹配的条件</li>
* <li>notLike: 字段值不模糊匹配的条件</li>
* <li>great: 字段值大于的条件</li>
* <li>less: 字段值小于的条件</li>
* <li>greatEqual: 字段值大于等于的条件</li>
* <li>lessEqual: 字段值小于等于的条件</li>
* <li>in: 字段值在指定范围内的条件</li>
* <li>notIn: 字段值不在指定范围内的条件</li>
* <li>between: 字段值在指定区间内的条件</li>
* <li>notBetween: 字段值不在指定区间内的条件</li>
* </ul>
*/
@Setter
@Getter
@ToString
public class Query {
/**
* 查询条件
*/
private Queryable query;
/**
* 排序条件列表
*/
private List<Sortable> sort;
/**
* 分页条件
*/
private Pageable page;
/**
* 可查询条件类,封装各种查询条件
*/
@Setter
@Getter
@ToString
public static class Queryable {
/**
* 指定字段值为null的条件列表
*/
private List<String> nullEqual;
/**
* 指定字段值不为null的条件列表
*/
private List<String> notNullEqual;
/**
* 指定字段值为空的条件列表(如空字符串、空集合等)
*/
private List<String> empty;
/**
* 指定字段值不为空的条件列表
*/
private List<String> notEmpty;
/**
* 指定字段值相等的条件映射(字段名 -> 值)
*/
private Map<String, Object> equal;
/**
* 指定字段值不相等的条件映射(字段名 -> 值)
*/
private Map<String, Object> notEqual;
/**
* 指定字段模糊匹配的条件映射(字段名 -> 匹配值)
*/
private Map<String, String> like;
/**
* 指定字段不模糊匹配的条件映射(字段名 -> 匹配值)
*/
private Map<String, String> notLike;
/**
* 指定字段包含指定字符串的条件映射(字段名 -> 包含值)
*/
private Map<String, String> contain;
/**
* 指定字段不包含指定字符串的条件映射(字段名 -> 不包含值)
*/
private Map<String, String> notContain;
/**
* 指定字段以指定字符串开头的条件映射(字段名 -> 开头值)
*/
private Map<String, String> startWith;
/**
* 指定字段不以指定字符串开头的条件映射(字段名 -> 不开头值)
*/
private Map<String, String> notStartWith;
/**
* 指定字段以指定字符串结尾的条件映射(字段名 -> 结尾值)
*/
private Map<String, String> endWith;
/**
* 指定字段不以指定字符串结尾的条件映射(字段名 -> 不结尾值)
*/
private Map<String, String> notEndWith;
/**
* 指定字段大于条件的映射(字段名 -> 值)
*/
private Map<String, Object> great;
/**
* 指定字段小于条件的映射(字段名 -> 值)
*/
private Map<String, Object> less;
/**
* 指定字段大于等于条件的映射(字段名 -> 值)
*/
private Map<String, Object> greatEqual;
/**
* 指定字段小于等于条件的映射(字段名 -> 值)
*/
private Map<String, Object> lessEqual;
/**
* 指定字段值在指定范围内的条件映射(字段名 -> 值列表)
*/
private Map<String, List<Object>> inside;
/**
* 指定字段值不在指定范围内的条件映射(字段名 -> 值列表)
*/
private Map<String, List<Object>> notInside;
/**
* 指定字段值在指定区间内的条件映射(字段名 -> 区间范围)
*/
private Map<String, Between> between;
/**
* 指定字段值不在指定区间内的条件映射(字段名 -> 区间范围)
*/
private Map<String, Between> notBetween;
/**
* 区间范围类,用于表示起始值和结束值
*/
@Setter
@Getter
@ToString
public static class Between {
/**
* 起始值
*/
private Object start;
/**
* 结束值
*/
private Object end;
}
}
/**
* 可排序条件类,用于指定排序字段和排序方向
*/
@Setter
@Getter
@ToString
public static class Sortable {
/**
* 排序字段名
*/
private String column;
/**
* 排序方向
*/
private Direction direction;
/**
* 排序方向枚举
*/
public enum Direction {
/**
* 升序排列
*/
ASC,
/**
* 降序排列
*/
DESC,
}
}
/**
* 可分页条件类,用于指定分页参数
*/
@Setter
@Getter
@ToString
public static class Pageable {
/**
* 页码索引从0开始
*/
private Integer index;
/**
* 每页大小
*/
private Integer size;
}
}

View File

@@ -1,5 +1,7 @@
package com.lanyuanxiaoyao.service.template.jpa.controller; package com.lanyuanxiaoyao.service.template.jpa.controller;
import com.lanyuanxiaoyao.service.template.common.controller.GlobalResponse;
import com.lanyuanxiaoyao.service.template.common.controller.SimpleController;
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity; import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity;
import com.lanyuanxiaoyao.service.template.jpa.service.SimpleServiceSupport; import com.lanyuanxiaoyao.service.template.jpa.service.SimpleServiceSupport;
@@ -158,14 +160,14 @@ public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_
@Transactional(readOnly = true) @Transactional(readOnly = true)
@PostMapping(LIST) @PostMapping(LIST)
@Override @Override
public GlobalResponse<Map<String, Object>> list(@RequestBody Query query) throws Exception { public GlobalResponse<Map<String, Object>> list(@RequestBody com.lanyuanxiaoyao.service.template.common.controller.Query query) throws Exception {
if (ObjectHelper.isNull(query)) { if (ObjectHelper.isNull(query)) {
return GlobalResponse.responseCrudData(List.of(), 0); return GlobalResponse.responseCrudData(List.of(), 0);
} }
var mapper = listItemMapper(); var mapper = listItemMapper();
var result = service.list(query); var result = service.list(query);
return GlobalResponse.responseCrudData( return GlobalResponse.responseCrudData(
result.get() result.items()
.map(entity -> { .map(entity -> {
try { try {
return mapper.apply(entity); return mapper.apply(entity);
@@ -174,7 +176,7 @@ public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_
} }
}) })
.toList(), .toList(),
result.getTotalElements() result.total()
); );
} }

View File

@@ -1,7 +1,9 @@
package com.lanyuanxiaoyao.service.template.jpa.service; package com.lanyuanxiaoyao.service.template.jpa.service;
import com.lanyuanxiaoyao.service.template.common.controller.Query;
import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper;
import com.lanyuanxiaoyao.service.template.jpa.controller.Query; import com.lanyuanxiaoyao.service.template.common.service.Page;
import com.lanyuanxiaoyao.service.template.common.service.SimpleService;
import com.lanyuanxiaoyao.service.template.jpa.entity.IdOnlyEntity; import com.lanyuanxiaoyao.service.template.jpa.entity.IdOnlyEntity;
import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity; import com.lanyuanxiaoyao.service.template.jpa.entity.SimpleEntity;
import com.lanyuanxiaoyao.service.template.jpa.repository.SimpleRepository; import com.lanyuanxiaoyao.service.template.jpa.repository.SimpleRepository;
@@ -20,7 +22,6 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.mapstruct.Named; import org.mapstruct.Named;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
@@ -267,148 +268,148 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
if (ObjectHelper.isNull(queryable)) { if (ObjectHelper.isNull(queryable)) {
return null; return null;
} }
if (ObjectHelper.isNotEmpty(queryable.getNullEqual())) { if (ObjectHelper.isNotEmpty(queryable.nullEqual())) {
queryable.getNullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column)))); queryable.nullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
} }
if (ObjectHelper.isNotEmpty(queryable.getNotNullEqual())) { if (ObjectHelper.isNotEmpty(queryable.notNullEqual())) {
queryable.getNotNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column)))); queryable.notNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column))));
} }
if (ObjectHelper.isNotEmpty(queryable.getEmpty())) { if (ObjectHelper.isNotEmpty(queryable.empty())) {
queryable.getEmpty().forEach(column -> { queryable.empty().forEach(column -> {
var path = this.<Collection<Object>>column(root, column); var path = this.<Collection<Object>>column(root, column);
checkCollection(path, column); checkCollection(path, column);
predicates.add(builder.isEmpty(path)); predicates.add(builder.isEmpty(path));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotEmpty())) { if (ObjectHelper.isNotEmpty(queryable.notEmpty())) {
queryable.getNotEmpty().forEach(column -> { queryable.notEmpty().forEach(column -> {
var path = this.<Collection<Object>>column(root, column); var path = this.<Collection<Object>>column(root, column);
checkCollection(path, column); checkCollection(path, column);
predicates.add(builder.isNotEmpty(path)); predicates.add(builder.isNotEmpty(path));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getEqual())) { if (ObjectHelper.isNotEmpty(queryable.equal())) {
queryable.getEqual().forEach((column, value) -> { queryable.equal().forEach((column, value) -> {
var path = column(root, column); var path = column(root, column);
predicates.add(builder.equal(path, value(path, value))); predicates.add(builder.equal(path, value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotEqual())) { if (ObjectHelper.isNotEmpty(queryable.notEqual())) {
queryable.getNotEqual().forEach((column, value) -> { queryable.notEqual().forEach((column, value) -> {
var path = column(root, column); var path = column(root, column);
predicates.add(builder.notEqual(path, value(path, value))); predicates.add(builder.notEqual(path, value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getLike())) { if (ObjectHelper.isNotEmpty(queryable.like())) {
queryable.getLike().forEach((column, value) -> { queryable.like().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.like(path, value)); predicates.add(builder.like(path, value));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotLike())) { if (ObjectHelper.isNotEmpty(queryable.notLike())) {
queryable.getNotLike().forEach((column, value) -> { queryable.notLike().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.notLike(path, value)); predicates.add(builder.notLike(path, value));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getContain())) { if (ObjectHelper.isNotEmpty(queryable.contain())) {
queryable.getContain().forEach((column, value) -> { queryable.contain().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.like(path, "%" + value + "%")); predicates.add(builder.like(path, "%" + value + "%"));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotContain())) { if (ObjectHelper.isNotEmpty(queryable.notContain())) {
queryable.getNotContain().forEach((column, value) -> { queryable.notContain().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.notLike(path, "%" + value + "%")); predicates.add(builder.notLike(path, "%" + value + "%"));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getStartWith())) { if (ObjectHelper.isNotEmpty(queryable.startWith())) {
queryable.getStartWith().forEach((column, value) -> { queryable.startWith().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.like(path, value + "%")); predicates.add(builder.like(path, value + "%"));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotStartWith())) { if (ObjectHelper.isNotEmpty(queryable.notStartWith())) {
queryable.getNotStartWith().forEach((column, value) -> { queryable.notStartWith().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.notLike(path, value + "%")); predicates.add(builder.notLike(path, value + "%"));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getEndWith())) { if (ObjectHelper.isNotEmpty(queryable.endWith())) {
queryable.getEndWith().forEach((column, value) -> { queryable.endWith().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.like(path, "%" + value)); predicates.add(builder.like(path, "%" + value));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotEndWith())) { if (ObjectHelper.isNotEmpty(queryable.notEndWith())) {
queryable.getNotEndWith().forEach((column, value) -> { queryable.notEndWith().forEach((column, value) -> {
var path = this.<String>column(root, column); var path = this.<String>column(root, column);
checkString(path, value, column); checkString(path, value, column);
predicates.add(builder.notLike(path, "%" + value)); predicates.add(builder.notLike(path, "%" + value));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getGreat())) { if (ObjectHelper.isNotEmpty(queryable.great())) {
queryable.getGreat().forEach((column, value) -> { queryable.great().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.greaterThan(path, (Comparable<Object>) value(path, value))); predicates.add(builder.greaterThan(path, (Comparable<Object>) value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getLess())) { if (ObjectHelper.isNotEmpty(queryable.less())) {
queryable.getLess().forEach((column, value) -> { queryable.less().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.lessThan(path, (Comparable<Object>) value(path, value))); predicates.add(builder.lessThan(path, (Comparable<Object>) value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getGreatEqual())) { if (ObjectHelper.isNotEmpty(queryable.greatEqual())) {
queryable.getGreatEqual().forEach((column, value) -> { queryable.greatEqual().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.greaterThanOrEqualTo(path, (Comparable<Object>) value(path, value))); predicates.add(builder.greaterThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getLessEqual())) { if (ObjectHelper.isNotEmpty(queryable.lessEqual())) {
queryable.getLessEqual().forEach((column, value) -> { queryable.lessEqual().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.lessThanOrEqualTo(path, (Comparable<Object>) value(path, value))); predicates.add(builder.lessThanOrEqualTo(path, (Comparable<Object>) value(path, value)));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getInside())) { if (ObjectHelper.isNotEmpty(queryable.inside())) {
queryable.getInside() queryable.inside()
.entrySet() .entrySet()
.stream() .stream()
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue()))); .forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue())));
} }
if (ObjectHelper.isNotEmpty(queryable.getNotInside())) { if (ObjectHelper.isNotEmpty(queryable.notInside())) {
queryable.getNotInside() queryable.notInside()
.entrySet() .entrySet()
.stream() .stream()
.filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue()))
.forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue()).not())); .forEach(entry -> predicates.add(builder.in(column(root, entry.getKey())).value(entry.getValue()).not()));
} }
if (ObjectHelper.isNotEmpty(queryable.getBetween())) { if (ObjectHelper.isNotEmpty(queryable.between())) {
queryable.getBetween().forEach((column, value) -> { queryable.between().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.getStart()), (Comparable<Object>) value(path, value.getEnd()))); predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())));
}); });
} }
if (ObjectHelper.isNotEmpty(queryable.getNotBetween())) { if (ObjectHelper.isNotEmpty(queryable.notBetween())) {
queryable.getNotBetween().forEach((column, value) -> { queryable.notBetween().forEach((column, value) -> {
var path = this.<Comparable<Object>>column(root, column); var path = this.<Comparable<Object>>column(root, column);
checkComparable(path, value, column); checkComparable(path, value, column);
predicates.add(builder.between(path, (Comparable<Object>) value(path, value.getStart()), (Comparable<Object>) value(path, value.getEnd())).not()); predicates.add(builder.between(path, (Comparable<Object>) value(path, value.start()), (Comparable<Object>) value(path, value.end())).not());
}); });
} }
@@ -438,8 +439,8 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
* @throws NotComparableException 当区间值不可比较时抛出 * @throws NotComparableException 当区间值不可比较时抛出
*/ */
private void checkComparable(Path<?> path, Query.Queryable.Between value, String column) { private void checkComparable(Path<?> path, Query.Queryable.Between value, String column) {
checkComparable(path, value.getStart(), column); checkComparable(path, value.start(), column);
checkComparable(path, value.getEnd(), column); checkComparable(path, value.end(), column);
} }
/** /**
@@ -510,30 +511,31 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
@Override @Override
public Page<ENTITY> list(Query listQuery) { public Page<ENTITY> list(Query listQuery) {
var pageRequest = PageRequest.of(DEFAULT_PAGE_INDEX - 1, DEFAULT_PAGE_SIZE, Sort.by(SimpleEntity.Fields.createdTime).descending()); var pageRequest = PageRequest.of(DEFAULT_PAGE_INDEX - 1, DEFAULT_PAGE_SIZE, Sort.by(SimpleEntity.Fields.createdTime).descending());
if (ObjectHelper.isNotNull(listQuery.getPage())) { if (ObjectHelper.isNotNull(listQuery.page())) {
var index = Math.max(ObjectHelper.defaultIfNull(listQuery.getPage().getIndex(), DEFAULT_PAGE_INDEX) - 1, 0); var index = Math.max(ObjectHelper.defaultIfNull(listQuery.page().index(), DEFAULT_PAGE_INDEX) - 1, 0);
var size = Math.max(ObjectHelper.defaultIfNull(listQuery.getPage().getSize(), DEFAULT_PAGE_SIZE), 1); var size = Math.max(ObjectHelper.defaultIfNull(listQuery.page().size(), DEFAULT_PAGE_SIZE), 1);
if (ObjectHelper.isNotEmpty(listQuery.getSort())) { if (ObjectHelper.isNotEmpty(listQuery.sort())) {
pageRequest = PageRequest.of(index, size, Sort.by( pageRequest = PageRequest.of(index, size, Sort.by(
listQuery.getSort() listQuery.sort()
.stream() .stream()
.map(sort -> new Sort.Order(Sort.Direction.fromString(sort.getDirection().name()), sort.getColumn())) .map(sort -> new Sort.Order(Sort.Direction.fromString(sort.direction().name()), sort.column()))
.toList() .toList()
)); ));
} else { } else {
pageRequest = PageRequest.of(index, size, Sort.by(SimpleEntity.Fields.createdTime).descending()); pageRequest = PageRequest.of(index, size, Sort.by(SimpleEntity.Fields.createdTime).descending());
} }
} }
return repository.findAll( var result = repository.findAll(
(root, query, builder) -> { (root, query, builder) -> {
var predicate = listPredicate(root, query, builder); var predicate = listPredicate(root, query, builder);
var queryPredicate = queryPredicates(listQuery.getQuery(), root, query, builder); var queryPredicate = queryPredicates(listQuery.query(), root, query, builder);
return ObjectHelper.isNull(predicate) return ObjectHelper.isNull(predicate)
? queryPredicate ? queryPredicate
: builder.and(predicate, queryPredicate); : builder.and(predicate, queryPredicate);
}, },
pageRequest pageRequest
); );
return new Page<>(result.get(), result.getTotalElements());
} }
/** /**

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lanyuanxiaoyao</groupId>
<artifactId>spring-boot-service-template</artifactId>
<version>1.1.0-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-service-template-web</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>