feat: 优化Global返回值
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller;
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 详情控制器接口,用于定义统一的获取实体详情的接口规范
|
* 详情控制器接口,用于定义统一的获取实体详情的接口规范
|
||||||
*
|
*
|
||||||
@@ -16,14 +14,14 @@ import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
public interface DetailController<DETAIL_ITEM> {
|
public interface DetailController<DETAIL_ITEM> {
|
||||||
String DETAIL = "/detail/{id}";
|
String DETAIL = "/detail/{id}";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID获取实体详情
|
* 根据ID获取实体详情
|
||||||
*
|
*
|
||||||
* @param id 实体ID
|
* @param id 实体ID
|
||||||
* @return GlobalResponse<DETAIL_ITEM> 返回实体详情
|
* @return GlobalResponse<DETAIL_ITEM> 返回实体详情
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
GlobalResponse<DETAIL_ITEM> detail(Long id) throws Exception;
|
GlobalResponse<DETAIL_ITEM> detail(Long id) throws Exception;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public class GlobalResponse<T> {
|
||||||
|
private static final int SUCCESS_STATUS = 0;
|
||||||
|
private static final int ERROR_STATUS = 500;
|
||||||
|
private static final String SUCCESS_MESSAGE = "OK";
|
||||||
|
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() {
|
||||||
|
return responseError(ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Object> responseError(String message) {
|
||||||
|
return new GlobalResponse<>(ERROR_STATUS, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Object> responseSuccess() {
|
||||||
|
return responseSuccess(SUCCESS_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Object> responseSuccess(String message) {
|
||||||
|
return responseSuccess(message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> GlobalResponse<E> responseSuccess(E data) {
|
||||||
|
return responseSuccess(SUCCESS_MESSAGE, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> GlobalResponse<E> responseSuccess(String message, E data) {
|
||||||
|
return new GlobalResponse<>(SUCCESS_STATUS, message, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Map<String, Object>> responseMapData(Map<String, Object> data) {
|
||||||
|
return responseSuccess(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Map<String, Object>> responseMapData(String key, Object value) {
|
||||||
|
return responseMapData(Map.of(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> GlobalResponse<Map<String, Object>> responseCrudData(Iterable<T> data, Integer total) {
|
||||||
|
return responseCrudData(data, total.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> GlobalResponse<Map<String, Object>> responseCrudData(Iterable<T> data, Long total) {
|
||||||
|
return responseMapData(Map.of("items", data, "total", total));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GlobalResponse<Map<String, Object>> responseDetailData(Object detail) {
|
||||||
|
return responseMapData("detail", detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller;
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalCrudResponse;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 列表控制器接口,用于定义统一的获取实体列表的接口规范
|
* 列表控制器接口,用于定义统一的获取实体列表的接口规范
|
||||||
@@ -57,22 +57,22 @@ import com.lanyuanxiaoyao.service.template.controller.response.GlobalCrudRespons
|
|||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
public interface ListController<LIST_ITEM> {
|
public interface ListController<LIST_ITEM> {
|
||||||
String LIST = "/list";
|
String LIST = "/list";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有实体列表
|
* 获取所有实体列表
|
||||||
*
|
*
|
||||||
* @return GlobalCrudResponse<LIST_ITEM> 返回实体列表
|
* @return GlobalCrudResponse<LIST_ITEM> 返回实体列表
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
GlobalCrudResponse<LIST_ITEM> list() throws Exception;
|
GlobalResponse<Map<String, Object>> list() throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据查询条件获取实体列表
|
* 根据查询条件获取实体列表
|
||||||
*
|
*
|
||||||
* @param query 查询条件对象
|
* @param query 查询条件对象
|
||||||
* @return GlobalCrudResponse<LIST_ITEM> 返回符合条件的实体列表
|
* @return GlobalCrudResponse<LIST_ITEM> 返回符合条件的实体列表
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
GlobalCrudResponse<LIST_ITEM> list(Query query) throws Exception;
|
GlobalResponse<Map<String, Object>> list(Query query) throws Exception;
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ import lombok.ToString;
|
|||||||
/**
|
/**
|
||||||
* 查询条件封装类,用于构建复杂的查询条件
|
* 查询条件封装类,用于构建复杂的查询条件
|
||||||
* 包含查询条件、排序条件和分页条件
|
* 包含查询条件、排序条件和分页条件
|
||||||
*
|
*
|
||||||
* <p>前端传入的JSON格式示例:</p>
|
* <p>前端传入的JSON格式示例:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* {
|
* {
|
||||||
@@ -45,7 +45,7 @@ import lombok.ToString;
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>查询条件说明:</p>
|
* <p>查询条件说明:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>nullEqual: 字段值为null的条件</li>
|
* <li>nullEqual: 字段值为null的条件</li>
|
||||||
@@ -70,154 +70,154 @@ import lombok.ToString;
|
|||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
public class Query {
|
public class Query {
|
||||||
|
/**
|
||||||
|
* 查询条件
|
||||||
|
*/
|
||||||
|
private Queryable query;
|
||||||
|
/**
|
||||||
|
* 排序条件列表
|
||||||
|
*/
|
||||||
|
private List<Sortable> sort;
|
||||||
|
/**
|
||||||
|
* 分页条件
|
||||||
|
*/
|
||||||
|
private Pageable page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可查询条件类,封装各种查询条件
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public static class Queryable {
|
||||||
/**
|
/**
|
||||||
* 查询条件
|
* 指定字段值为null的条件列表
|
||||||
*/
|
*/
|
||||||
private Queryable query;
|
private List<String> nullEqual;
|
||||||
/**
|
/**
|
||||||
* 排序条件列表
|
* 指定字段值不为null的条件列表
|
||||||
*/
|
*/
|
||||||
private List<Sortable> sort;
|
private List<String> notNullEqual;
|
||||||
/**
|
/**
|
||||||
* 分页条件
|
* 指定字段值为空的条件列表(如空字符串、空集合等)
|
||||||
*/
|
*/
|
||||||
private Pageable page;
|
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, Object> great;
|
||||||
|
/**
|
||||||
|
* 指定字段小于条件的映射(字段名 -> 值)
|
||||||
|
*/
|
||||||
|
private Map<String, Object> less;
|
||||||
|
/**
|
||||||
|
* 指定字段大于等于条件的映射(字段名 -> 值)
|
||||||
|
*/
|
||||||
|
private Map<String, Object> greatEqual;
|
||||||
|
/**
|
||||||
|
* 指定字段小于等于条件的映射(字段名 -> 值)
|
||||||
|
*/
|
||||||
|
private Map<String, Object> lessEqual;
|
||||||
|
/**
|
||||||
|
* 指定字段值在指定范围内的条件映射(字段名 -> 值列表)
|
||||||
|
*/
|
||||||
|
private Map<String, List<Object>> in;
|
||||||
|
/**
|
||||||
|
* 指定字段值不在指定范围内的条件映射(字段名 -> 值列表)
|
||||||
|
*/
|
||||||
|
private Map<String, List<Object>> notIn;
|
||||||
|
/**
|
||||||
|
* 指定字段值在指定区间内的条件映射(字段名 -> 区间范围)
|
||||||
|
*/
|
||||||
|
private Map<String, Between> between;
|
||||||
|
/**
|
||||||
|
* 指定字段值不在指定区间内的条件映射(字段名 -> 区间范围)
|
||||||
|
*/
|
||||||
|
private Map<String, Between> notBetween;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可查询条件类,封装各种查询条件
|
* 区间范围类,用于表示起始值和结束值
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
public static class Queryable {
|
public static class Between {
|
||||||
/**
|
/**
|
||||||
* 指定字段值为null的条件列表
|
* 起始值
|
||||||
*/
|
*/
|
||||||
private List<String> nullEqual;
|
private Object start;
|
||||||
/**
|
/**
|
||||||
* 指定字段值不为null的条件列表
|
* 结束值
|
||||||
*/
|
*/
|
||||||
private List<String> notNullEqual;
|
private Object end;
|
||||||
/**
|
|
||||||
* 指定字段值为空的条件列表(如空字符串、空集合等)
|
|
||||||
*/
|
|
||||||
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, Object> great;
|
|
||||||
/**
|
|
||||||
* 指定字段小于条件的映射(字段名 -> 值)
|
|
||||||
*/
|
|
||||||
private Map<String, Object> less;
|
|
||||||
/**
|
|
||||||
* 指定字段大于等于条件的映射(字段名 -> 值)
|
|
||||||
*/
|
|
||||||
private Map<String, Object> greatEqual;
|
|
||||||
/**
|
|
||||||
* 指定字段小于等于条件的映射(字段名 -> 值)
|
|
||||||
*/
|
|
||||||
private Map<String, Object> lessEqual;
|
|
||||||
/**
|
|
||||||
* 指定字段值在指定范围内的条件映射(字段名 -> 值列表)
|
|
||||||
*/
|
|
||||||
private Map<String, List<Object>> in;
|
|
||||||
/**
|
|
||||||
* 指定字段值不在指定范围内的条件映射(字段名 -> 值列表)
|
|
||||||
*/
|
|
||||||
private Map<String, List<Object>> notIn;
|
|
||||||
/**
|
|
||||||
* 指定字段值在指定区间内的条件映射(字段名 -> 区间范围)
|
|
||||||
*/
|
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可排序条件类,用于指定排序字段和排序方向
|
* 排序方向枚举
|
||||||
*/
|
*/
|
||||||
@Setter
|
public enum Direction {
|
||||||
@Getter
|
/**
|
||||||
@ToString
|
* 升序排列
|
||||||
public static class Sortable {
|
*/
|
||||||
/**
|
ASC,
|
||||||
* 排序字段名
|
/**
|
||||||
*/
|
* 降序排列
|
||||||
private String column;
|
*/
|
||||||
/**
|
DESC,
|
||||||
* 排序方向
|
|
||||||
*/
|
|
||||||
private Direction direction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 排序方向枚举
|
|
||||||
*/
|
|
||||||
public enum Direction {
|
|
||||||
/**
|
|
||||||
* 升序排列
|
|
||||||
*/
|
|
||||||
ASC,
|
|
||||||
/**
|
|
||||||
* 降序排列
|
|
||||||
*/
|
|
||||||
DESC,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可分页条件类,用于指定分页参数
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public static class Pageable {
|
||||||
/**
|
/**
|
||||||
* 可分页条件类,用于指定分页参数
|
* 页码索引(从0开始)
|
||||||
*/
|
*/
|
||||||
@Setter
|
private Integer index;
|
||||||
@Getter
|
/**
|
||||||
@ToString
|
* 每页大小
|
||||||
public static class Pageable {
|
*/
|
||||||
/**
|
private Integer size;
|
||||||
* 页码索引(从0开始)
|
}
|
||||||
*/
|
|
||||||
private Integer index;
|
|
||||||
/**
|
|
||||||
* 每页大小
|
|
||||||
*/
|
|
||||||
private Integer size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller;
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除控制器接口,用于定义统一的删除实体对象的接口规范
|
* 删除控制器接口,用于定义统一的删除实体对象的接口规范
|
||||||
*
|
*
|
||||||
@@ -15,14 +13,14 @@ import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
public interface RemoveController {
|
public interface RemoveController {
|
||||||
String REMOVE = "/remove/{id}";
|
String REMOVE = "/remove/{id}";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID删除实体对象
|
* 根据ID删除实体对象
|
||||||
*
|
*
|
||||||
* @param id 需要删除的实体ID
|
* @param id 需要删除的实体ID
|
||||||
* @return GlobalResponse<Object> 返回删除结果
|
* @return GlobalResponse<Object> 返回删除结果
|
||||||
* @throws Exception 删除过程中可能抛出的异常
|
* @throws Exception 删除过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
GlobalResponse<Object> remove(Long id) throws Exception;
|
GlobalResponse<Object> remove(Long id) throws Exception;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller;
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存控制器接口,用于定义统一的保存实体对象的接口规范
|
* 保存控制器接口,用于定义统一的保存实体对象的接口规范
|
||||||
*
|
*
|
||||||
@@ -19,14 +17,14 @@ import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
public interface SaveController<SAVE_ITEM> {
|
public interface SaveController<SAVE_ITEM> {
|
||||||
String SAVE = "/save";
|
String SAVE = "/save";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存实体对象
|
* 保存实体对象
|
||||||
*
|
*
|
||||||
* @param item 需要保存的实体对象
|
* @param item 需要保存的实体对象
|
||||||
* @return GlobalResponse<Long> 返回保存后的实体ID
|
* @return GlobalResponse<Long> 返回保存后的实体ID
|
||||||
* @throws Exception 保存过程中可能抛出的异常
|
* @throws Exception 保存过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
GlobalResponse<Long> save(SAVE_ITEM item) throws Exception;
|
GlobalResponse<Long> save(SAVE_ITEM item) throws Exception;
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller;
|
package com.lanyuanxiaoyao.service.template.controller;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalCrudResponse;
|
|
||||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
|
||||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||||
import com.lanyuanxiaoyao.service.template.helper.ObjectHelper;
|
import com.lanyuanxiaoyao.service.template.helper.ObjectHelper;
|
||||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -87,140 +86,140 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
* </ul>
|
* </ul>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param <ENTITY> 实体类型,必须继承SimpleEntity
|
* @param <ENTITY> 实体类型,必须继承SimpleEntity
|
||||||
* @param <SAVE_ITEM> 保存项类型
|
* @param <SAVE_ITEM> 保存项类型
|
||||||
* @param <LIST_ITEM> 列表项类型
|
* @param <LIST_ITEM> 列表项类型
|
||||||
* @param <DETAIL_ITEM> 详情项类型
|
* @param <DETAIL_ITEM> 详情项类型
|
||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> implements SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> {
|
public abstract class SimpleControllerSupport<ENTITY extends SimpleEntity, SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> implements SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> {
|
||||||
protected final SimpleServiceSupport<ENTITY> service;
|
protected final SimpleServiceSupport<ENTITY> service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数
|
* 构造函数
|
||||||
*
|
*
|
||||||
* @param service 简单服务支持类实例
|
* @param service 简单服务支持类实例
|
||||||
*/
|
*/
|
||||||
public SimpleControllerSupport(SimpleServiceSupport<ENTITY> service) {
|
public SimpleControllerSupport(SimpleServiceSupport<ENTITY> service) {
|
||||||
this.service = service;
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存实体对象
|
||||||
|
*
|
||||||
|
* @param item 需要保存的项
|
||||||
|
* @return GlobalResponse<Long> 返回保存后的实体ID
|
||||||
|
* @throws Exception 保存过程中可能抛出的异常
|
||||||
|
*/
|
||||||
|
@PostMapping(SAVE)
|
||||||
|
@Override
|
||||||
|
public GlobalResponse<Long> save(@RequestBody SAVE_ITEM item) throws Exception {
|
||||||
|
var mapper = saveItemMapper();
|
||||||
|
return GlobalResponse.responseSuccess(service.save(mapper.apply(item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有实体列表
|
||||||
|
*
|
||||||
|
* @return GlobalCrudResponse<LIST_ITEM> 返回实体列表
|
||||||
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
|
*/
|
||||||
|
@GetMapping(LIST)
|
||||||
|
@Override
|
||||||
|
public GlobalResponse<Map<String, Object>> list() throws Exception {
|
||||||
|
var mapper = listItemMapper();
|
||||||
|
var result = service.list();
|
||||||
|
return GlobalResponse.responseCrudData(
|
||||||
|
result
|
||||||
|
.stream()
|
||||||
|
.map(entity -> {
|
||||||
|
try {
|
||||||
|
return mapper.apply(entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
result.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据查询条件获取实体列表
|
||||||
|
*
|
||||||
|
* @param query 查询条件对象
|
||||||
|
* @return GlobalCrudResponse<LIST_ITEM> 返回符合条件的实体列表
|
||||||
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
|
*/
|
||||||
|
@PostMapping(LIST)
|
||||||
|
@Override
|
||||||
|
public GlobalResponse<Map<String, Object>> list(@RequestBody Query query) throws Exception {
|
||||||
|
if (ObjectHelper.isNull(query)) {
|
||||||
|
return GlobalResponse.responseCrudData(List.of(), 0);
|
||||||
}
|
}
|
||||||
|
var mapper = listItemMapper();
|
||||||
|
var result = service.list(query);
|
||||||
|
return GlobalResponse.responseCrudData(
|
||||||
|
result.get()
|
||||||
|
.map(entity -> {
|
||||||
|
try {
|
||||||
|
return mapper.apply(entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
result.getTotalElements()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存实体对象
|
* 根据ID获取实体详情
|
||||||
*
|
*
|
||||||
* @param item 需要保存的项
|
* @param id 实体ID
|
||||||
* @return GlobalResponse<Long> 返回保存后的实体ID
|
* @return GlobalResponse<DETAIL_ITEM> 返回实体详情
|
||||||
* @throws Exception 保存过程中可能抛出的异常
|
* @throws Exception 查询过程中可能抛出的异常
|
||||||
*/
|
*/
|
||||||
@PostMapping(SAVE)
|
@GetMapping(DETAIL)
|
||||||
@Override
|
@Override
|
||||||
public GlobalResponse<Long> save(@RequestBody SAVE_ITEM item) throws Exception {
|
public GlobalResponse<DETAIL_ITEM> detail(@PathVariable("id") Long id) throws Exception {
|
||||||
var mapper = saveItemMapper();
|
var mapper = detailItemMapper();
|
||||||
return GlobalResponse.responseSuccess(service.save(mapper.apply(item)));
|
return GlobalResponse.responseSuccess(mapper.apply(service.detailOrThrow(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有实体列表
|
* 根据ID删除实体对象
|
||||||
*
|
*
|
||||||
* @return GlobalCrudResponse<LIST_ITEM> 返回实体列表
|
* @param id 需要删除的实体ID
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
* @return GlobalResponse<Object> 返回删除结果
|
||||||
*/
|
* @throws Exception 删除过程中可能抛出的异常
|
||||||
@GetMapping(LIST)
|
*/
|
||||||
@Override
|
@GetMapping(REMOVE)
|
||||||
public GlobalCrudResponse<LIST_ITEM> list() throws Exception {
|
@Override
|
||||||
var mapper = listItemMapper();
|
public GlobalResponse<Object> remove(@PathVariable("id") Long id) throws Exception {
|
||||||
var result = service.list();
|
service.remove(id);
|
||||||
return GlobalCrudResponse.responseCrudData(
|
return GlobalResponse.responseSuccess();
|
||||||
result
|
}
|
||||||
.stream()
|
|
||||||
.map(entity -> {
|
|
||||||
try {
|
|
||||||
return mapper.apply(entity);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toList(),
|
|
||||||
result.size()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据查询条件获取实体列表
|
* 保存项映射器,将保存项转换为实体对象
|
||||||
*
|
*
|
||||||
* @param query 查询条件对象
|
* @return Function<SAVE_ITEM, ENTITY> 保存项到实体的转换函数
|
||||||
* @return GlobalCrudResponse<LIST_ITEM> 返回符合条件的实体列表
|
*/
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
protected abstract Function<SAVE_ITEM, ENTITY> saveItemMapper();
|
||||||
*/
|
|
||||||
@PostMapping(LIST)
|
|
||||||
@Override
|
|
||||||
public GlobalCrudResponse<LIST_ITEM> list(@RequestBody Query query) throws Exception {
|
|
||||||
if (ObjectHelper.isNull(query)) {
|
|
||||||
return GlobalCrudResponse.responseCrudData(List.of(), 0);
|
|
||||||
}
|
|
||||||
var mapper = listItemMapper();
|
|
||||||
var result = service.list(query);
|
|
||||||
return GlobalCrudResponse.responseCrudData(
|
|
||||||
result.get()
|
|
||||||
.map(entity -> {
|
|
||||||
try {
|
|
||||||
return mapper.apply(entity);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.toList(),
|
|
||||||
result.getTotalElements()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID获取实体详情
|
* 列表项映射器,将实体对象转换为列表项
|
||||||
*
|
*
|
||||||
* @param id 实体ID
|
* @return Function<ENTITY, LIST_ITEM> 实体到列表项的转换函数
|
||||||
* @return GlobalResponse<DETAIL_ITEM> 返回实体详情
|
*/
|
||||||
* @throws Exception 查询过程中可能抛出的异常
|
protected abstract Function<ENTITY, LIST_ITEM> listItemMapper();
|
||||||
*/
|
|
||||||
@GetMapping(DETAIL)
|
|
||||||
@Override
|
|
||||||
public GlobalResponse<DETAIL_ITEM> detail(@PathVariable("id") Long id) throws Exception {
|
|
||||||
var mapper = detailItemMapper();
|
|
||||||
return GlobalResponse.responseSuccess(mapper.apply(service.detailOrThrow(id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID删除实体对象
|
* 详情项映射器,将实体对象转换为详情项
|
||||||
*
|
*
|
||||||
* @param id 需要删除的实体ID
|
* @return Function<ENTITY, DETAIL_ITEM> 实体到详情项的转换函数
|
||||||
* @return GlobalResponse<Object> 返回删除结果
|
*/
|
||||||
* @throws Exception 删除过程中可能抛出的异常
|
protected abstract Function<ENTITY, DETAIL_ITEM> detailItemMapper();
|
||||||
*/
|
|
||||||
@GetMapping(REMOVE)
|
|
||||||
@Override
|
|
||||||
public GlobalResponse<Object> remove(@PathVariable("id") Long id) throws Exception {
|
|
||||||
service.remove(id);
|
|
||||||
return GlobalResponse.responseSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存项映射器,将保存项转换为实体对象
|
|
||||||
*
|
|
||||||
* @return Function<SAVE_ITEM, ENTITY> 保存项到实体的转换函数
|
|
||||||
*/
|
|
||||||
protected abstract Function<SAVE_ITEM, ENTITY> saveItemMapper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表项映射器,将实体对象转换为列表项
|
|
||||||
*
|
|
||||||
* @return Function<ENTITY, LIST_ITEM> 实体到列表项的转换函数
|
|
||||||
*/
|
|
||||||
protected abstract Function<ENTITY, LIST_ITEM> listItemMapper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 详情项映射器,将实体对象转换为详情项
|
|
||||||
*
|
|
||||||
* @return Function<ENTITY, DETAIL_ITEM> 实体到详情项的转换函数
|
|
||||||
*/
|
|
||||||
protected abstract Function<ENTITY, DETAIL_ITEM> detailItemMapper();
|
|
||||||
}
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
|
||||||
|
|
||||||
public class GlobalCrudResponse<T> extends GlobalMapResponse {
|
|
||||||
public void setData(Iterable<T> list) {
|
|
||||||
setData("items", list);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(Long total) {
|
|
||||||
setData("total", total);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(Integer total) {
|
|
||||||
setTotal(total.longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(Iterable<T> list, Long total) {
|
|
||||||
setData(list);
|
|
||||||
setTotal(total);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(Iterable<T> list, Integer total) {
|
|
||||||
setData(list, total.longValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
|
||||||
|
|
||||||
public class GlobalDetailResponse extends GlobalMapResponse {
|
|
||||||
public void setDetail(Object detail) {
|
|
||||||
setData("detail", detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class GlobalMapResponse extends GlobalResponse<Map<String, Object>> {
|
|
||||||
public GlobalMapResponse() {
|
|
||||||
setData(new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public GlobalMapResponse setData(String key, Object value) {
|
|
||||||
getData().put(key, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
@ToString
|
|
||||||
public class GlobalResponse<T> {
|
|
||||||
private static final int SUCCESS_STATUS = 0;
|
|
||||||
private static final int ERROR_STATUS = 500;
|
|
||||||
private static final String SUCCESS_MESSAGE = "OK";
|
|
||||||
private static final String ERROR_MESSAGE = "ERROR";
|
|
||||||
private Integer status;
|
|
||||||
private String message;
|
|
||||||
private T data;
|
|
||||||
|
|
||||||
public static GlobalResponse<Object> responseError() {
|
|
||||||
return responseError(ERROR_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalResponse<Object> responseError(String message) {
|
|
||||||
GlobalResponse<Object> response = new GlobalResponse<>();
|
|
||||||
response.setStatus(ERROR_STATUS);
|
|
||||||
response.setMessage(message);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalResponse<Object> responseSuccess() {
|
|
||||||
GlobalResponse<Object> response = new GlobalResponse<>();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(SUCCESS_MESSAGE);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalResponse<Object> responseSuccess(String message) {
|
|
||||||
GlobalResponse<Object> response = new GlobalResponse<>();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(message);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> GlobalResponse<E> responseSuccess(String message, E data) {
|
|
||||||
GlobalResponse<E> response = new GlobalResponse<>();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(message);
|
|
||||||
response.setData(data);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <E> GlobalResponse<E> responseSuccess(E data) {
|
|
||||||
GlobalResponse<E> response = new GlobalResponse<>();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(SUCCESS_MESSAGE);
|
|
||||||
response.setData(data);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalMapResponse responseMapData() {
|
|
||||||
GlobalMapResponse response = new GlobalMapResponse();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(SUCCESS_MESSAGE);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalMapResponse responseMapData(Map<String, Object> data) {
|
|
||||||
GlobalMapResponse response = responseMapData();
|
|
||||||
response.setData(data);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalMapResponse responseMapData(String key, Object value) {
|
|
||||||
GlobalMapResponse response = responseMapData();
|
|
||||||
response.setData(key, value);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> GlobalCrudResponse<T> responseCrudData(Iterable<T> data) {
|
|
||||||
GlobalCrudResponse<T> response = new GlobalCrudResponse<>();
|
|
||||||
response.setStatus(SUCCESS_STATUS);
|
|
||||||
response.setMessage(SUCCESS_MESSAGE);
|
|
||||||
response.setData(data);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> GlobalCrudResponse<T> responseCrudData(Iterable<T> data, Integer total) {
|
|
||||||
GlobalCrudResponse<T> response = responseCrudData(data);
|
|
||||||
response.setTotal(total);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> GlobalCrudResponse<T> responseCrudData(Iterable<T> data, Long total) {
|
|
||||||
GlobalCrudResponse<T> response = responseCrudData(data);
|
|
||||||
response.setTotal(total);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalDetailResponse responseDetailData(Object detail) {
|
|
||||||
GlobalDetailResponse response = new GlobalDetailResponse();
|
|
||||||
response.setDetail(detail);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -38,14 +38,14 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@EntityListeners(AuditingEntityListener.class)
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
public class IdOnlyEntity {
|
public class IdOnlyEntity {
|
||||||
/**
|
/**
|
||||||
* 实体唯一标识符
|
* 实体唯一标识符
|
||||||
* <p>
|
* <p>
|
||||||
* 使用Snowflake算法生成的Long类型ID,保证全局唯一性。
|
* 使用Snowflake算法生成的Long类型ID,保证全局唯一性。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Id
|
@Id
|
||||||
@SnowflakeId
|
@SnowflakeId
|
||||||
@Comment("记录唯一标记")
|
@Comment("记录唯一标记")
|
||||||
private Long id;
|
private Long id;
|
||||||
}
|
}
|
||||||
@@ -39,23 +39,23 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@EntityListeners(AuditingEntityListener.class)
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
public class SimpleEntity extends IdOnlyEntity {
|
public class SimpleEntity extends IdOnlyEntity {
|
||||||
/**
|
/**
|
||||||
* 记录创建时间
|
* 记录创建时间
|
||||||
* <p>
|
* <p>
|
||||||
* 由Spring Data JPA自动维护,当实体首次持久化时设置该字段的值。
|
* 由Spring Data JPA自动维护,当实体首次持久化时设置该字段的值。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@CreatedDate
|
@CreatedDate
|
||||||
@Comment("记录创建时间")
|
@Comment("记录创建时间")
|
||||||
private LocalDateTime createdTime;
|
private LocalDateTime createdTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录更新时间
|
* 记录更新时间
|
||||||
* <p>
|
* <p>
|
||||||
* 由Spring Data JPA自动维护,当实体每次更新时刷新该字段的值。
|
* 由Spring Data JPA自动维护,当实体每次更新时刷新该字段的值。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@LastModifiedDate
|
@LastModifiedDate
|
||||||
@Comment("记录更新时间")
|
@Comment("记录更新时间")
|
||||||
private LocalDateTime modifiedTime;
|
private LocalDateTime modifiedTime;
|
||||||
}
|
}
|
||||||
@@ -5,105 +5,105 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class ObjectHelper {
|
public class ObjectHelper {
|
||||||
/**
|
/**
|
||||||
* 判断对象是否为null
|
* 判断对象是否为null
|
||||||
*
|
*
|
||||||
* @param obj 待检查的对象
|
* @param obj 待检查的对象
|
||||||
* @return 如果对象为null返回true,否则返回false
|
* @return 如果对象为null返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
public static boolean isNull(Object obj) {
|
public static boolean isNull(Object obj) {
|
||||||
return obj == null;
|
return obj == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象是否不为null
|
* 判断对象是否不为null
|
||||||
*
|
*
|
||||||
* @param obj 待判断的对象
|
* @param obj 待判断的对象
|
||||||
* @return 如果对象不为null则返回true,否则返回false
|
* @return 如果对象不为null则返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
public static boolean isNotNull(Object obj) {
|
public static boolean isNotNull(Object obj) {
|
||||||
return !isNull(obj);
|
return !isNull(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象是否为空
|
* 判断对象是否为空
|
||||||
*
|
*
|
||||||
* @param obj 待判断的对象
|
* @param obj 待判断的对象
|
||||||
* @return 如果对象为null或为空则返回true,否则返回false
|
* @return 如果对象为null或为空则返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
public static boolean isEmpty(Object obj) {
|
public static boolean isEmpty(Object obj) {
|
||||||
// 首先判断对象是否为null
|
// 首先判断对象是否为null
|
||||||
if (isNull(obj)) return true;
|
if (isNull(obj)) return true;
|
||||||
// 判断是否为集合类型
|
// 判断是否为集合类型
|
||||||
else if (obj instanceof Collection<?> collection) return collection.isEmpty();
|
else if (obj instanceof Collection<?> collection) return collection.isEmpty();
|
||||||
// 判断是否为Map类型
|
// 判断是否为Map类型
|
||||||
else if (obj instanceof Map<?, ?> map) return map.isEmpty();
|
else if (obj instanceof Map<?, ?> map) return map.isEmpty();
|
||||||
// 判断是否为字符序列类型
|
// 判断是否为字符序列类型
|
||||||
else if (obj instanceof CharSequence sequence) return sequence.isEmpty();
|
else if (obj instanceof CharSequence sequence) return sequence.isEmpty();
|
||||||
// 判断是否为各种基本类型数组
|
// 判断是否为各种基本类型数组
|
||||||
else if (obj instanceof Object[] array) return array.length == 0;
|
else if (obj instanceof Object[] array) return array.length == 0;
|
||||||
else if (obj instanceof byte[] array) return array.length == 0;
|
else if (obj instanceof byte[] array) return array.length == 0;
|
||||||
else if (obj instanceof short[] array) return array.length == 0;
|
else if (obj instanceof short[] array) return array.length == 0;
|
||||||
else if (obj instanceof int[] array) return array.length == 0;
|
else if (obj instanceof int[] array) return array.length == 0;
|
||||||
else if (obj instanceof long[] array) return array.length == 0;
|
else if (obj instanceof long[] array) return array.length == 0;
|
||||||
else if (obj instanceof float[] array) return array.length == 0;
|
else if (obj instanceof float[] array) return array.length == 0;
|
||||||
else if (obj instanceof double[] array) return array.length == 0;
|
else if (obj instanceof double[] array) return array.length == 0;
|
||||||
else if (obj instanceof char[] array) return array.length == 0;
|
else if (obj instanceof char[] array) return array.length == 0;
|
||||||
else if (obj instanceof boolean[] array) return array.length == 0;
|
else if (obj instanceof boolean[] array) return array.length == 0;
|
||||||
// 判断是否为Optional类型
|
// 判断是否为Optional类型
|
||||||
else if (obj instanceof Optional<?> optional) return optional.isEmpty();
|
else if (obj instanceof Optional<?> optional) return optional.isEmpty();
|
||||||
// 其他情况认为对象不为空
|
// 其他情况认为对象不为空
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isNotEmpty(Object obj) {
|
public static boolean isNotEmpty(Object obj) {
|
||||||
return !isEmpty(obj);
|
return !isEmpty(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
||||||
return isNull(object) ? defaultValue : object;
|
return isNull(object) ? defaultValue : object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断给定的类是否可比较
|
* 判断给定的类是否可比较
|
||||||
*
|
*
|
||||||
* @param clazz 待判断的类对象
|
* @param clazz 待判断的类对象
|
||||||
* @return 如果类是枚举、字符序列、可比较接口的实现类或基本数据类型则返回true,否则返回false
|
* @return 如果类是枚举、字符序列、可比较接口的实现类或基本数据类型则返回true,否则返回false
|
||||||
*/
|
*/
|
||||||
public static boolean isComparable(Class<?> clazz) {
|
public static boolean isComparable(Class<?> clazz) {
|
||||||
if (isNull(clazz)) return false;
|
if (isNull(clazz)) return false;
|
||||||
// 判断类是否为可比较类型:枚举、字符序列、可比较接口实现类或基本数据类型
|
// 判断类是否为可比较类型:枚举、字符序列、可比较接口实现类或基本数据类型
|
||||||
return clazz.isEnum() ||
|
return clazz.isEnum() ||
|
||||||
CharSequence.class.isAssignableFrom(clazz) ||
|
CharSequence.class.isAssignableFrom(clazz) ||
|
||||||
Comparable.class.isAssignableFrom(clazz) ||
|
Comparable.class.isAssignableFrom(clazz) ||
|
||||||
clazz.isPrimitive();
|
clazz.isPrimitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isComparable(Object obj) {
|
public static boolean isComparable(Object obj) {
|
||||||
if (isNull(obj)) return false;
|
if (isNull(obj)) return false;
|
||||||
return isComparable(obj.getClass());
|
return isComparable(obj.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCollection(Class<?> clazz) {
|
public static boolean isCollection(Class<?> clazz) {
|
||||||
if (isNull(clazz)) return false;
|
if (isNull(clazz)) return false;
|
||||||
return Collection.class.isAssignableFrom(clazz);
|
return Collection.class.isAssignableFrom(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCollection(Object obj) {
|
public static boolean isCollection(Object obj) {
|
||||||
if (isNull(obj)) return false;
|
if (isNull(obj)) return false;
|
||||||
return isCollection(obj.getClass());
|
return isCollection(obj.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isString(Class<?> clazz) {
|
public static boolean isString(Class<?> clazz) {
|
||||||
if (isNull(clazz)) return false;
|
if (isNull(clazz)) return false;
|
||||||
return String.class.isAssignableFrom(clazz);
|
return String.class.isAssignableFrom(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isString(Object obj) {
|
public static boolean isString(Object obj) {
|
||||||
if (isNull(obj)) return false;
|
if (isNull(obj)) return false;
|
||||||
return isString(obj.getClass());
|
return isString(obj.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ import org.springframework.data.repository.query.QueryByExampleExecutor;
|
|||||||
* </ul>
|
* </ul>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param <E> 实体类型
|
* @param <E> 实体类型
|
||||||
* @param <ID> 实体ID类型
|
* @param <ID> 实体ID类型
|
||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ import java.util.Set;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
public interface SimpleService<ENTITY extends SimpleEntity> {
|
public interface SimpleService<ENTITY extends SimpleEntity> {
|
||||||
Long save(ENTITY entity) throws Exception;
|
Long save(ENTITY entity) throws Exception;
|
||||||
|
|
||||||
Long count() throws Exception;
|
Long count() throws Exception;
|
||||||
|
|
||||||
List<ENTITY> list() throws Exception;
|
List<ENTITY> list() throws Exception;
|
||||||
|
|
||||||
List<ENTITY> list(Set<Long> ids) throws Exception;
|
List<ENTITY> list(Set<Long> ids) throws Exception;
|
||||||
|
|
||||||
Page<ENTITY> list(Query query) throws Exception;
|
Page<ENTITY> list(Query query) throws Exception;
|
||||||
|
|
||||||
Optional<ENTITY> detailOptional(Long id) throws Exception;
|
Optional<ENTITY> detailOptional(Long id) throws Exception;
|
||||||
|
|
||||||
ENTITY detail(Long id) throws Exception;
|
ENTITY detail(Long id) throws Exception;
|
||||||
|
|
||||||
ENTITY detailOrThrow(Long id) throws Exception;
|
ENTITY detailOrThrow(Long id) throws Exception;
|
||||||
|
|
||||||
ENTITY detailOrNull(Long id) throws Exception;
|
ENTITY detailOrNull(Long id) throws Exception;
|
||||||
|
|
||||||
void remove(Long id) throws Exception;
|
void remove(Long id) throws Exception;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,161 +25,161 @@ import org.springframework.web.client.RestTemplate;
|
|||||||
@EnableFenix
|
@EnableFenix
|
||||||
@EnableJpaAuditing
|
@EnableJpaAuditing
|
||||||
public class TestApplication {
|
public class TestApplication {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TestApplication.class);
|
private static final Logger log = LoggerFactory.getLogger(TestApplication.class);
|
||||||
private static final String BASE_URL = "http://localhost:2490";
|
private static final String BASE_URL = "http://localhost:2490";
|
||||||
private static final RestTemplate REST_CLIENT = new RestTemplate();
|
private static final RestTemplate REST_CLIENT = new RestTemplate();
|
||||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(TestApplication.class, args);
|
SpringApplication.run(TestApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
@EventListener(ApplicationReadyEvent.class)
|
||||||
public void runTests() throws JsonProcessingException {
|
public void runTests() throws JsonProcessingException {
|
||||||
// 增
|
// 增
|
||||||
var cid1 = saveItem("company", "{\"name\": \"Apple\",\"members\": 10}").get("data").asLong();
|
var cid1 = saveItem("company", "{\"name\": \"Apple\",\"members\": 10}").get("data").asLong();
|
||||||
var cid2 = saveItem("company", "{\"name\": \"Banana\",\"members\": 20}").get("data").asLong();
|
var cid2 = saveItem("company", "{\"name\": \"Banana\",\"members\": 20}").get("data").asLong();
|
||||||
var cid3 = saveItem("company", "{\"name\": \"Cheery\",\"members\": 20}").get("data").asLong();
|
var cid3 = saveItem("company", "{\"name\": \"Cheery\",\"members\": 20}").get("data").asLong();
|
||||||
|
|
||||||
// 查
|
// 查
|
||||||
var companies = listItems("company");
|
var companies = listItems("company");
|
||||||
Assert.isTrue(companies.at("/data/items").size() == 3, "数量错误");
|
Assert.isTrue(companies.at("/data/items").size() == 3, "数量错误");
|
||||||
Assert.isTrue(companies.at("/data/total").asLong() == 3, "返回数量错误");
|
Assert.isTrue(companies.at("/data/total").asLong() == 3, "返回数量错误");
|
||||||
|
|
||||||
// language=JSON
|
// language=JSON
|
||||||
var companies2 = listItems("company", "{\n" +
|
var companies2 = listItems("company", "{\n" +
|
||||||
" \"page\": {\n" +
|
" \"page\": {\n" +
|
||||||
" \"index\": 1,\n" +
|
" \"index\": 1,\n" +
|
||||||
" \"size\": 2\n" +
|
" \"size\": 2\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"}");
|
"}");
|
||||||
Assert.isTrue(companies2.at("/data/items").size() == 2, "数量错误");
|
Assert.isTrue(companies2.at("/data/items").size() == 2, "数量错误");
|
||||||
Assert.isTrue(companies2.at("/data/total").asLong() == 3, "返回数量错误");
|
Assert.isTrue(companies2.at("/data/total").asLong() == 3, "返回数量错误");
|
||||||
// language=JSON
|
// language=JSON
|
||||||
var companies3 = listItems("company", "{\n" +
|
var companies3 = listItems("company", "{\n" +
|
||||||
" \"query\": {\n" +
|
" \"query\": {\n" +
|
||||||
" \"notNullEqual\": [\n" +
|
" \"notNullEqual\": [\n" +
|
||||||
" \"name\"\n" +
|
" \"name\"\n" +
|
||||||
" ],\n" +
|
" ],\n" +
|
||||||
" \"equal\": {\n" +
|
" \"equal\": {\n" +
|
||||||
" \"name\": \"Apple\"\n" +
|
" \"name\": \"Apple\"\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"like\": {\n" +
|
" \"like\": {\n" +
|
||||||
" \"name\": \"Appl%\"\n" +
|
" \"name\": \"Appl%\"\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"less\": {\n" +
|
" \"less\": {\n" +
|
||||||
" \"members\": 50\n" +
|
" \"members\": 50\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"greatEqual\": {\n" +
|
" \"greatEqual\": {\n" +
|
||||||
" \"members\": 0\n" +
|
" \"members\": 0\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"in\": {\n" +
|
" \"in\": {\n" +
|
||||||
" \"name\": [\n" +
|
" \"name\": [\n" +
|
||||||
" \"Apple\",\n" +
|
" \"Apple\",\n" +
|
||||||
" \"Banana\"\n" +
|
" \"Banana\"\n" +
|
||||||
" ]\n" +
|
" ]\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"between\": {\n" +
|
" \"between\": {\n" +
|
||||||
" \"members\": {\n" +
|
" \"members\": {\n" +
|
||||||
" \"start\": 0,\n" +
|
" \"start\": 0,\n" +
|
||||||
" \"end\": 50\n" +
|
" \"end\": 50\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" },\n" +
|
" },\n" +
|
||||||
" \"page\": {\n" +
|
" \"page\": {\n" +
|
||||||
" \"index\": 1,\n" +
|
" \"index\": 1,\n" +
|
||||||
" \"size\": 2\n" +
|
" \"size\": 2\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"}");
|
"}");
|
||||||
Assert.isTrue(companies3.at("/data/items").size() == 1, "数量错误");
|
Assert.isTrue(companies3.at("/data/items").size() == 1, "数量错误");
|
||||||
Assert.isTrue(companies3.at("/data/total").asLong() == 1, "返回数量错误");
|
Assert.isTrue(companies3.at("/data/total").asLong() == 1, "返回数量错误");
|
||||||
|
|
||||||
var company1 = detailItem("company", cid1);
|
var company1 = detailItem("company", cid1);
|
||||||
Assert.isTrue(cid1 == company1.at("/data/id").asLong(), "id错误");
|
Assert.isTrue(cid1 == company1.at("/data/id").asLong(), "id错误");
|
||||||
Assert.isTrue("Apple".equals(company1.at("/data/name").asText()), "name错误");
|
Assert.isTrue("Apple".equals(company1.at("/data/name").asText()), "name错误");
|
||||||
|
|
||||||
// 改
|
// 改
|
||||||
var cid4 = saveItem("company", "{\"id\": %d, \"name\": \"Dog\"}".formatted(cid2)).get("data").asLong();
|
var cid4 = saveItem("company", "{\"id\": %d, \"name\": \"Dog\"}".formatted(cid2)).get("data").asLong();
|
||||||
Assert.isTrue(cid2 == cid4, "id错误");
|
Assert.isTrue(cid2 == cid4, "id错误");
|
||||||
var company2 = detailItem("company", cid2);
|
var company2 = detailItem("company", cid2);
|
||||||
Assert.isTrue("Dog".equals(company2.at("/data/name").asText()), "name错误");
|
Assert.isTrue("Dog".equals(company2.at("/data/name").asText()), "name错误");
|
||||||
|
|
||||||
// 删
|
// 删
|
||||||
removeItem("company", cid3);
|
removeItem("company", cid3);
|
||||||
Assert.isTrue(listItems("company").at("/data/items").size() == 2, "数量错误");
|
Assert.isTrue(listItems("company").at("/data/items").size() == 2, "数量错误");
|
||||||
Assert.isTrue(listItems("company").at("/data/total").asLong() == 2, "返回数量错误");
|
Assert.isTrue(listItems("company").at("/data/total").asLong() == 2, "返回数量错误");
|
||||||
|
|
||||||
log.info(listItems("company").toPrettyString());
|
log.info(listItems("company").toPrettyString());
|
||||||
|
|
||||||
var eid1 = saveItem("employee", "{\"name\": \"Tom\",\"age\": 18, \"companyId\": %d}".formatted(cid1)).get("data").asLong();
|
var eid1 = saveItem("employee", "{\"name\": \"Tom\",\"age\": 18, \"companyId\": %d}".formatted(cid1)).get("data").asLong();
|
||||||
var eid2 = saveItem("employee", "{\"name\": \"Jerry\",\"age\": 18, \"companyId\": %d}".formatted(cid1)).get("data").asLong();
|
var eid2 = saveItem("employee", "{\"name\": \"Jerry\",\"age\": 18, \"companyId\": %d}".formatted(cid1)).get("data").asLong();
|
||||||
var eid3 = saveItem("employee", "{\"name\": \"Mike\",\"age\": 18, \"companyId\": %d}".formatted(cid2)).get("data").asLong();
|
var eid3 = saveItem("employee", "{\"name\": \"Mike\",\"age\": 18, \"companyId\": %d}".formatted(cid2)).get("data").asLong();
|
||||||
|
|
||||||
var employees = listItems("employee");
|
var employees = listItems("employee");
|
||||||
Assert.isTrue(employees.at("/data/items").size() == 3, "数量错误");
|
Assert.isTrue(employees.at("/data/items").size() == 3, "数量错误");
|
||||||
Assert.isTrue(employees.at("/data/total").asLong() == 3, "返回数量错误");
|
Assert.isTrue(employees.at("/data/total").asLong() == 3, "返回数量错误");
|
||||||
|
|
||||||
var employee1 = detailItem("employee", eid1);
|
var employee1 = detailItem("employee", eid1);
|
||||||
Assert.isTrue(eid1 == employee1.at("/data/id").asLong(), "id错误");
|
Assert.isTrue(eid1 == employee1.at("/data/id").asLong(), "id错误");
|
||||||
Assert.isTrue("Tom".equals(employee1.at("/data/name").asText()), "name错误");
|
Assert.isTrue("Tom".equals(employee1.at("/data/name").asText()), "name错误");
|
||||||
Assert.isTrue(18 == employee1.at("/data/age").asInt(), "age错误");
|
Assert.isTrue(18 == employee1.at("/data/age").asInt(), "age错误");
|
||||||
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpHeaders headers() {
|
private HttpHeaders headers() {
|
||||||
var headers = new HttpHeaders();
|
var headers = new HttpHeaders();
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode saveItem(String path, String body) throws JsonProcessingException {
|
private JsonNode saveItem(String path, String body) throws JsonProcessingException {
|
||||||
var response = REST_CLIENT.postForEntity(
|
var response = REST_CLIENT.postForEntity(
|
||||||
"%s/%s/save".formatted(BASE_URL, path),
|
"%s/%s/save".formatted(BASE_URL, path),
|
||||||
new HttpEntity<>(body, headers()),
|
new HttpEntity<>(body, headers()),
|
||||||
String.class
|
String.class
|
||||||
);
|
);
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
Assert.notNull(response.getBody(), "请求失败");
|
||||||
return MAPPER.readTree(response.getBody());
|
return MAPPER.readTree(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode listItems(String path) throws JsonProcessingException {
|
private JsonNode listItems(String path) throws JsonProcessingException {
|
||||||
var response = REST_CLIENT.getForEntity(
|
var response = REST_CLIENT.getForEntity(
|
||||||
"%s/%s/list".formatted(BASE_URL, path),
|
"%s/%s/list".formatted(BASE_URL, path),
|
||||||
String.class
|
String.class
|
||||||
);
|
);
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
Assert.notNull(response.getBody(), "请求失败");
|
||||||
return MAPPER.readTree(response.getBody());
|
return MAPPER.readTree(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode listItems(String path, String query) throws JsonProcessingException {
|
private JsonNode listItems(String path, String query) throws JsonProcessingException {
|
||||||
var response = REST_CLIENT.postForEntity(
|
var response = REST_CLIENT.postForEntity(
|
||||||
"%s/%s/list".formatted(BASE_URL, path),
|
"%s/%s/list".formatted(BASE_URL, path),
|
||||||
new HttpEntity<>(query, headers()),
|
new HttpEntity<>(query, headers()),
|
||||||
String.class
|
String.class
|
||||||
);
|
);
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
Assert.notNull(response.getBody(), "请求失败");
|
||||||
return MAPPER.readTree(response.getBody());
|
return MAPPER.readTree(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode detailItem(String path, Long id) throws JsonProcessingException {
|
private JsonNode detailItem(String path, Long id) throws JsonProcessingException {
|
||||||
var response = REST_CLIENT.getForEntity(
|
var response = REST_CLIENT.getForEntity(
|
||||||
"%s/%s/detail/%d".formatted(BASE_URL, path, id),
|
"%s/%s/detail/%d".formatted(BASE_URL, path, id),
|
||||||
String.class
|
String.class
|
||||||
);
|
);
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
||||||
Assert.notNull(response.getBody(), "请求失败");
|
Assert.notNull(response.getBody(), "请求失败");
|
||||||
return MAPPER.readTree(response.getBody());
|
return MAPPER.readTree(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeItem(String path, Long id) {
|
private void removeItem(String path, Long id) {
|
||||||
var response = REST_CLIENT.getForEntity(
|
var response = REST_CLIENT.getForEntity(
|
||||||
"%s/%s/remove/%d".formatted(BASE_URL, path, id),
|
"%s/%s/remove/%d".formatted(BASE_URL, path, id),
|
||||||
Void.class
|
Void.class
|
||||||
);
|
);
|
||||||
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,73 +15,73 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("company")
|
@RequestMapping("company")
|
||||||
public class CompanyController extends SimpleControllerSupport<Company, CompanyController.SaveItem, CompanyController.ListItem, CompanyController.DetailItem> {
|
public class CompanyController extends SimpleControllerSupport<Company, CompanyController.SaveItem, CompanyController.ListItem, CompanyController.DetailItem> {
|
||||||
public CompanyController(CompanyService service) {
|
public CompanyController(CompanyService service) {
|
||||||
super(service);
|
super(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<SaveItem, Company> saveItemMapper() {
|
protected Function<SaveItem, Company> saveItemMapper() {
|
||||||
return item -> {
|
return item -> {
|
||||||
var company = new Company();
|
var company = new Company();
|
||||||
company.setId(item.getId());
|
company.setId(item.getId());
|
||||||
company.setName(item.getName());
|
company.setName(item.getName());
|
||||||
company.setMembers(item.getMembers());
|
company.setMembers(item.getMembers());
|
||||||
return company;
|
return company;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<Company, ListItem> listItemMapper() {
|
protected Function<Company, ListItem> listItemMapper() {
|
||||||
return company -> new ListItem(
|
return company -> new ListItem(
|
||||||
company.getId(),
|
company.getId(),
|
||||||
company.getName(),
|
company.getName(),
|
||||||
company.getMembers()
|
company.getMembers()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<Company, DetailItem> detailItemMapper() {
|
protected Function<Company, DetailItem> detailItemMapper() {
|
||||||
return company -> new DetailItem(
|
return company -> new DetailItem(
|
||||||
company.getId(),
|
company.getId(),
|
||||||
company.getName(),
|
company.getName(),
|
||||||
company.getMembers(),
|
company.getMembers(),
|
||||||
company.getCreatedTime(),
|
company.getCreatedTime(),
|
||||||
company.getModifiedTime()
|
company.getModifiedTime()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class SaveItem {
|
public static class SaveItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer members;
|
private Integer members;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class ListItem {
|
public static class ListItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer members;
|
private Integer members;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class DetailItem {
|
public static class DetailItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer members;
|
private Integer members;
|
||||||
private LocalDateTime createdTime;
|
private LocalDateTime createdTime;
|
||||||
private LocalDateTime modifiedTime;
|
private LocalDateTime modifiedTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,85 +16,85 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("employee")
|
@RequestMapping("employee")
|
||||||
public class EmployeeController extends SimpleControllerSupport<Employee, EmployeeController.SaveItem, EmployeeController.ListItem, EmployeeController.DetailItem> {
|
public class EmployeeController extends SimpleControllerSupport<Employee, EmployeeController.SaveItem, EmployeeController.ListItem, EmployeeController.DetailItem> {
|
||||||
private final CompanyService companyService;
|
private final CompanyService companyService;
|
||||||
|
|
||||||
public EmployeeController(EmployeeService service, CompanyService companyService) {
|
public EmployeeController(EmployeeService service, CompanyService companyService) {
|
||||||
super(service);
|
super(service);
|
||||||
this.companyService = companyService;
|
this.companyService = companyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<SaveItem, Employee> saveItemMapper() {
|
protected Function<SaveItem, Employee> saveItemMapper() {
|
||||||
return item -> {
|
return item -> {
|
||||||
var employee = new Employee();
|
var employee = new Employee();
|
||||||
employee.setId(item.getId());
|
employee.setId(item.getId());
|
||||||
employee.setName(item.getName());
|
employee.setName(item.getName());
|
||||||
employee.setAge(item.getAge());
|
employee.setAge(item.getAge());
|
||||||
employee.setRole(Employee.Role.USER);
|
employee.setRole(Employee.Role.USER);
|
||||||
employee.setCompany(companyService.detailOrThrow(item.getCompanyId()));
|
employee.setCompany(companyService.detailOrThrow(item.getCompanyId()));
|
||||||
return employee;
|
return employee;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<Employee, ListItem> listItemMapper() {
|
protected Function<Employee, ListItem> listItemMapper() {
|
||||||
return employee -> new ListItem(
|
return employee -> new ListItem(
|
||||||
employee.getId(),
|
employee.getId(),
|
||||||
employee.getName(),
|
employee.getName(),
|
||||||
employee.getAge(),
|
employee.getAge(),
|
||||||
employee.getRole()
|
employee.getRole()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Function<Employee, DetailItem> detailItemMapper() {
|
protected Function<Employee, DetailItem> detailItemMapper() {
|
||||||
return employee -> new DetailItem(
|
return employee -> new DetailItem(
|
||||||
employee.getId(),
|
employee.getId(),
|
||||||
employee.getCompany().getId(),
|
employee.getCompany().getId(),
|
||||||
employee.getName(),
|
employee.getName(),
|
||||||
employee.getAge(),
|
employee.getAge(),
|
||||||
employee.getRole(),
|
employee.getRole(),
|
||||||
employee.getCreatedTime(),
|
employee.getCreatedTime(),
|
||||||
employee.getModifiedTime()
|
employee.getModifiedTime()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class SaveItem {
|
public static class SaveItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long companyId;
|
private Long companyId;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer age;
|
private Integer age;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class ListItem {
|
public static class ListItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer age;
|
private Integer age;
|
||||||
private Employee.Role role;
|
private Employee.Role role;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class DetailItem {
|
public static class DetailItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long companyId;
|
private Long companyId;
|
||||||
private String name;
|
private String name;
|
||||||
private Integer age;
|
private Integer age;
|
||||||
private Employee.Role role;
|
private Employee.Role role;
|
||||||
private LocalDateTime createdTime;
|
private LocalDateTime createdTime;
|
||||||
private LocalDateTime modifiedTime;
|
private LocalDateTime modifiedTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|||||||
@EntityListeners(AuditingEntityListener.class)
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
@Comment("企业")
|
@Comment("企业")
|
||||||
public class Company extends SimpleEntity {
|
public class Company extends SimpleEntity {
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Comment("名称")
|
@Comment("名称")
|
||||||
private String name;
|
private String name;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Comment("成员数")
|
@Comment("成员数")
|
||||||
private Integer members;
|
private Integer members;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "company")
|
@OneToMany(mappedBy = "company")
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
private Set<Employee> employees;
|
private Set<Employee> employees;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,28 +28,28 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|||||||
@DynamicUpdate
|
@DynamicUpdate
|
||||||
@EntityListeners(AuditingEntityListener.class)
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
@NamedEntityGraph(name = "employee.detail", attributeNodes = {
|
@NamedEntityGraph(name = "employee.detail", attributeNodes = {
|
||||||
@NamedAttributeNode("company")
|
@NamedAttributeNode("company")
|
||||||
})
|
})
|
||||||
@Comment("员工")
|
@Comment("员工")
|
||||||
public class Employee extends SimpleEntity {
|
public class Employee extends SimpleEntity {
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Comment("名称")
|
@Comment("名称")
|
||||||
private String name;
|
private String name;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Comment("年龄")
|
@Comment("年龄")
|
||||||
private Integer age;
|
private Integer age;
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@Comment("角色")
|
@Comment("角色")
|
||||||
private Role role;
|
private Role role;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
private Company company;
|
private Company company;
|
||||||
|
|
||||||
public enum Role {
|
public enum Role {
|
||||||
USER,
|
USER,
|
||||||
ADMIN,
|
ADMIN,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository;
|
|||||||
@SuppressWarnings("NullableProblems")
|
@SuppressWarnings("NullableProblems")
|
||||||
@Repository
|
@Repository
|
||||||
public interface EmployeeRepository extends SimpleRepository<Employee, Long> {
|
public interface EmployeeRepository extends SimpleRepository<Employee, Long> {
|
||||||
@EntityGraph(value = "employee.detail", type = EntityGraph.EntityGraphType.FETCH)
|
@EntityGraph(value = "employee.detail", type = EntityGraph.EntityGraphType.FETCH)
|
||||||
@Override
|
@Override
|
||||||
Optional<Employee> findOne(Specification<Employee> specification);
|
Optional<Employee> findOne(Specification<Employee> specification);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CompanyService extends SimpleServiceSupport<Company> {
|
public class CompanyService extends SimpleServiceSupport<Company> {
|
||||||
public CompanyService(CompanyRepository repository) {
|
public CompanyService(CompanyRepository repository) {
|
||||||
super(repository);
|
super(repository);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class EmployeeService extends SimpleServiceSupport<Employee> {
|
public class EmployeeService extends SimpleServiceSupport<Employee> {
|
||||||
public EmployeeService(EmployeeRepository repository) {
|
public EmployeeService(EmployeeRepository repository) {
|
||||||
super(repository);
|
super(repository);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user