feat: 完成基本功能
This commit is contained in:
134
.gitignore
vendored
Normal file
134
.gitignore
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
.idea
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/**/aws.xml
|
||||
.idea/**/contentModel.xml
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
cmake-build-*/
|
||||
.idea/**/mongoSettings.xml
|
||||
*.iws
|
||||
out/
|
||||
.idea_modules/
|
||||
atlassian-ide-plugin.xml
|
||||
.idea/replstate.xml
|
||||
.idea/sonarlint/
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
.idea/httpRequests
|
||||
.idea/caches/build_file_checksums.ser
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
.project
|
||||
.classpath
|
||||
*.class
|
||||
*.log
|
||||
*.ctxt
|
||||
.mtj.tmp/
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
.history/
|
||||
*.vsix
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
.externalToolBuilders/
|
||||
*.launch
|
||||
*.pydevproject
|
||||
.cproject
|
||||
.autotools
|
||||
.factorypath
|
||||
.buildpath
|
||||
.target
|
||||
.tern-project
|
||||
.texlipse
|
||||
.springBeans
|
||||
.recommenders/
|
||||
.apt_generated/
|
||||
.apt_generated_test/
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
*.stackdump
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
*~
|
||||
.fuse_hidden*
|
||||
.directory
|
||||
.Trash-*
|
||||
.nfs*
|
||||
.gradle
|
||||
**/build/
|
||||
!src/**/build/
|
||||
gradle-app.setting
|
||||
!gradle-wrapper.jar
|
||||
!gradle-wrapper.properties
|
||||
.gradletasknamecache
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
._*
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
70
pom.xml
Normal file
70
pom.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>
|
||||
|
||||
<groupId>com.lanyuanxiaoyao</groupId>
|
||||
<artifactId>spring-boot-service-template</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<spring-boot.version>3.4.3</spring-boot.version>
|
||||
<spring-cloud.version>2024.0.1</spring-cloud.version>
|
||||
<eclipse-collections.version>11.1.0</eclipse-collections.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.blinkfox</groupId>
|
||||
<artifactId>fenix-spring-boot-starter</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- spring boot 相关依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>${releases.id}</id>
|
||||
<name>${releases.name}</name>
|
||||
<url>${releases.url}</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>${snapshots.id}</id>
|
||||
<name>${snapshots.name}</name>
|
||||
<url>${snapshots.url}</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
||||
|
||||
public interface DetailController<DETAIL_ITEM> {
|
||||
String DETAIL = "/detail/{id}";
|
||||
|
||||
GlobalResponse<DETAIL_ITEM> detail(Long id) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalCrudResponse;
|
||||
|
||||
public interface ListController<LIST_ITEM> {
|
||||
String LIST = "/list";
|
||||
|
||||
GlobalCrudResponse<LIST_ITEM> list() throws Exception;
|
||||
|
||||
GlobalCrudResponse<LIST_ITEM> list(Query query) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Query {
|
||||
private Queryable query;
|
||||
private List<Sortable> sort;
|
||||
private Pageable page;
|
||||
|
||||
public Queryable getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(Queryable query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public List<Sortable> getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void setSort(List<Sortable> sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
public Pageable getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(Pageable page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Query{" +
|
||||
"query=" + query +
|
||||
", sort=" + sort +
|
||||
", page=" + page +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static class Queryable {
|
||||
private List<String> nullEqual;
|
||||
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, Comparable<Object>> great;
|
||||
private Map<String, Comparable<Object>> less;
|
||||
private Map<String, Comparable<Object>> greatEqual;
|
||||
private Map<String, Comparable<Object>> lessEqual;
|
||||
private Map<String, List<Object>> in;
|
||||
private Map<String, List<Object>> notIn;
|
||||
private Map<String, Between> between;
|
||||
private Map<String, Between> notBetween;
|
||||
|
||||
public java.util.List<String> getNullEqual() {
|
||||
return nullEqual;
|
||||
}
|
||||
|
||||
public void setNullEqual(java.util.List<String> nullEqual) {
|
||||
this.nullEqual = nullEqual;
|
||||
}
|
||||
|
||||
public java.util.List<String> getNotNullEqual() {
|
||||
return notNullEqual;
|
||||
}
|
||||
|
||||
public void setNotNullEqual(java.util.List<String> notNullEqual) {
|
||||
this.notNullEqual = notNullEqual;
|
||||
}
|
||||
|
||||
public java.util.List<String> getEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
public void setEmpty(java.util.List<String> empty) {
|
||||
this.empty = empty;
|
||||
}
|
||||
|
||||
public java.util.List<String> getNotEmpty() {
|
||||
return notEmpty;
|
||||
}
|
||||
|
||||
public void setNotEmpty(java.util.List<String> notEmpty) {
|
||||
this.notEmpty = notEmpty;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Object> getEqual() {
|
||||
return equal;
|
||||
}
|
||||
|
||||
public void setEqual(java.util.Map<String, Object> equal) {
|
||||
this.equal = equal;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Object> getNotEqual() {
|
||||
return notEqual;
|
||||
}
|
||||
|
||||
public void setNotEqual(java.util.Map<String, Object> notEqual) {
|
||||
this.notEqual = notEqual;
|
||||
}
|
||||
|
||||
public java.util.Map<String, String> getLike() {
|
||||
return like;
|
||||
}
|
||||
|
||||
public void setLike(java.util.Map<String, String> like) {
|
||||
this.like = like;
|
||||
}
|
||||
|
||||
public java.util.Map<String, String> getNotLike() {
|
||||
return notLike;
|
||||
}
|
||||
|
||||
public void setNotLike(java.util.Map<String, String> notLike) {
|
||||
this.notLike = notLike;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Comparable<Object>> getGreat() {
|
||||
return great;
|
||||
}
|
||||
|
||||
public void setGreat(java.util.Map<String, Comparable<Object>> great) {
|
||||
this.great = great;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Comparable<Object>> getLess() {
|
||||
return less;
|
||||
}
|
||||
|
||||
public void setLess(java.util.Map<String, Comparable<Object>> less) {
|
||||
this.less = less;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Comparable<Object>> getGreatEqual() {
|
||||
return greatEqual;
|
||||
}
|
||||
|
||||
public void setGreatEqual(java.util.Map<String, Comparable<Object>> greatEqual) {
|
||||
this.greatEqual = greatEqual;
|
||||
}
|
||||
|
||||
public java.util.Map<String, Comparable<Object>> getLessEqual() {
|
||||
return lessEqual;
|
||||
}
|
||||
|
||||
public void setLessEqual(java.util.Map<String, Comparable<Object>> lessEqual) {
|
||||
this.lessEqual = lessEqual;
|
||||
}
|
||||
|
||||
public java.util.Map<String, java.util.List<Object>> getIn() {
|
||||
return in;
|
||||
}
|
||||
|
||||
public void setIn(java.util.Map<String, java.util.List<Object>> in) {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
public java.util.Map<String, java.util.List<Object>> getNotIn() {
|
||||
return notIn;
|
||||
}
|
||||
|
||||
public void setNotIn(java.util.Map<String, java.util.List<Object>> notIn) {
|
||||
this.notIn = notIn;
|
||||
}
|
||||
|
||||
public java.util.Map<String, com.lanyuanxiaoyao.service.template.controller.Query.Queryable.Between> getBetween() {
|
||||
return between;
|
||||
}
|
||||
|
||||
public void setBetween(java.util.Map<String, com.lanyuanxiaoyao.service.template.controller.Query.Queryable.Between> between) {
|
||||
this.between = between;
|
||||
}
|
||||
|
||||
public java.util.Map<String, com.lanyuanxiaoyao.service.template.controller.Query.Queryable.Between> getNotBetween() {
|
||||
return notBetween;
|
||||
}
|
||||
|
||||
public void setNotBetween(java.util.Map<String, com.lanyuanxiaoyao.service.template.controller.Query.Queryable.Between> notBetween) {
|
||||
this.notBetween = notBetween;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Queryable{" +
|
||||
"nullEqual=" + nullEqual +
|
||||
", notNullEqual=" + notNullEqual +
|
||||
", empty=" + empty +
|
||||
", notEmpty=" + notEmpty +
|
||||
", equal=" + equal +
|
||||
", notEqual=" + notEqual +
|
||||
", like=" + like +
|
||||
", notLike=" + notLike +
|
||||
", great=" + great +
|
||||
", less=" + less +
|
||||
", greatEqual=" + greatEqual +
|
||||
", lessEqual=" + lessEqual +
|
||||
", in=" + in +
|
||||
", notIn=" + notIn +
|
||||
", between=" + between +
|
||||
", notBetween=" + notBetween +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static class Between {
|
||||
private String start;
|
||||
private String end;
|
||||
|
||||
public String getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(String start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public String getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(String end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Between{" +
|
||||
"start='" + start + '\'' +
|
||||
", end='" + end + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Sortable {
|
||||
private String column;
|
||||
private Direction direction;
|
||||
|
||||
public String getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
public void setColumn(String column) {
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
public Direction getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sortable{" +
|
||||
"column='" + column + '\'' +
|
||||
", direction=" + direction +
|
||||
'}';
|
||||
}
|
||||
|
||||
public enum Direction {
|
||||
ASC,
|
||||
DESC,
|
||||
}
|
||||
}
|
||||
|
||||
public static class Pageable {
|
||||
private Integer index;
|
||||
private Integer size;
|
||||
|
||||
public Integer getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Integer index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Integer size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pageable{" +
|
||||
"index=" + index +
|
||||
", size=" + size +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
||||
|
||||
public interface RemoveController {
|
||||
String REMOVE = "/remove/{id}";
|
||||
|
||||
GlobalResponse<Object> remove(Long id) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.response.GlobalResponse;
|
||||
|
||||
public interface SaveController<SAVE_ITEM> {
|
||||
String SAVE = "/save";
|
||||
|
||||
GlobalResponse<Long> save(SAVE_ITEM item) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller;
|
||||
|
||||
public interface SimpleController<SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> extends SaveController<SAVE_ITEM>, ListController<LIST_ITEM>, DetailController<DETAIL_ITEM>, RemoveController {
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
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.helper.ObjectHelper;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
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;
|
||||
|
||||
public SimpleControllerSupport(SimpleServiceSupport<ENTITY> service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@PostMapping(SAVE)
|
||||
@Override
|
||||
public GlobalResponse<Long> save(@RequestBody SAVE_ITEM item) throws Exception {
|
||||
SaveItemMapper<ENTITY, SAVE_ITEM> mapper = saveItemMapper();
|
||||
return GlobalResponse.responseSuccess(service.save(mapper.from(item)));
|
||||
}
|
||||
|
||||
@GetMapping(LIST)
|
||||
@Override
|
||||
public GlobalCrudResponse<LIST_ITEM> list() throws Exception {
|
||||
ListItemMapper<ENTITY, LIST_ITEM> mapper = listItemMapper();
|
||||
return GlobalCrudResponse.responseCrudData(
|
||||
service.list()
|
||||
.stream()
|
||||
.map(entity -> {
|
||||
try {
|
||||
return mapper.from(entity);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
|
||||
@PostMapping(LIST)
|
||||
@Override
|
||||
public GlobalCrudResponse<LIST_ITEM> list(@RequestBody Query query) throws Exception {
|
||||
if (ObjectHelper.isNull(query)) {
|
||||
return GlobalCrudResponse.responseCrudData(List.of(), 0);
|
||||
}
|
||||
ListItemMapper<ENTITY, LIST_ITEM> mapper = listItemMapper();
|
||||
Page<ENTITY> result = service.list(query);
|
||||
return GlobalCrudResponse.responseCrudData(
|
||||
result.get()
|
||||
.map(entity -> {
|
||||
try {
|
||||
return mapper.from(entity);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.toList(),
|
||||
result.getTotalElements()
|
||||
);
|
||||
}
|
||||
|
||||
@GetMapping(DETAIL)
|
||||
@Override
|
||||
public GlobalResponse<DETAIL_ITEM> detail(@PathVariable("id") Long id) throws Exception {
|
||||
DetailItemMapper<ENTITY, DETAIL_ITEM> mapper = detailItemMapper();
|
||||
return GlobalResponse.responseSuccess(mapper.from(service.detailOrThrow(id)));
|
||||
}
|
||||
|
||||
@GetMapping(REMOVE)
|
||||
@Override
|
||||
public GlobalResponse<Object> remove(@PathVariable("id") Long id) throws Exception {
|
||||
service.remove(id);
|
||||
return GlobalResponse.responseSuccess();
|
||||
}
|
||||
|
||||
protected abstract SaveItemMapper<ENTITY, SAVE_ITEM> saveItemMapper();
|
||||
|
||||
protected abstract ListItemMapper<ENTITY, LIST_ITEM> listItemMapper();
|
||||
|
||||
protected abstract DetailItemMapper<ENTITY, DETAIL_ITEM> detailItemMapper();
|
||||
|
||||
public interface SaveItemMapper<ENTITY, SAVE_ITEM> {
|
||||
ENTITY from(SAVE_ITEM item) throws Exception;
|
||||
}
|
||||
|
||||
public interface ListItemMapper<ENTITY, LIST_ITEM> {
|
||||
LIST_ITEM from(ENTITY entity) throws Exception;
|
||||
}
|
||||
|
||||
public interface DetailItemMapper<ENTITY, DETAIL_ITEM> {
|
||||
DETAIL_ITEM from(ENTITY entity) throws Exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
||||
|
||||
/**
|
||||
* Crud 响应
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2023-07-06
|
||||
*/
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
||||
|
||||
/**
|
||||
* Crud 响应
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2023-07-06
|
||||
*/
|
||||
public class GlobalDetailResponse extends GlobalMapResponse {
|
||||
public void setDetail(Object detail) {
|
||||
setData("detail", detail);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map 响应
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2023-07-06
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.lanyuanxiaoyao.service.template.controller.response;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Amis 组件结构化返回值
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2022-09-21
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AmisResponse{" +
|
||||
"status=" + status +
|
||||
", message='" + message + '\'' +
|
||||
", data=" + data +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lanyuanxiaoyao.service.template.entity;
|
||||
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import org.hibernate.annotations.Comment;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class IdOnlyEntity {
|
||||
@Comment("记录唯一标记")
|
||||
@Id
|
||||
@GeneratedValue(generator = "snowflake")
|
||||
@GenericGenerator(name = "snowflake", strategy = "com.lanyuanxiaoyao.service.ai.web.configuration.SnowflakeIdGenerator")
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IdOnlyEntity{" +
|
||||
"id=" + id +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lanyuanxiaoyao.service.template.entity;
|
||||
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import java.time.LocalDateTime;
|
||||
import org.hibernate.annotations.Comment;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class SimpleEntity extends IdOnlyEntity {
|
||||
@Comment("记录创建时间")
|
||||
@CreatedDate
|
||||
private LocalDateTime createdTime;
|
||||
@Comment("记录更新时间")
|
||||
@LastModifiedDate
|
||||
private LocalDateTime modifiedTime;
|
||||
|
||||
public LocalDateTime getCreatedTime() {
|
||||
return createdTime;
|
||||
}
|
||||
|
||||
public void setCreatedTime(LocalDateTime createdTime) {
|
||||
this.createdTime = createdTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getModifiedTime() {
|
||||
return modifiedTime;
|
||||
}
|
||||
|
||||
public void setModifiedTime(LocalDateTime modifiedTime) {
|
||||
this.modifiedTime = modifiedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleEntity{" +
|
||||
"createdTime=" + createdTime +
|
||||
", modifiedTime=" + modifiedTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lanyuanxiaoyao.service.template.helper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ObjectHelper {
|
||||
public static boolean isNull(Object obj) {
|
||||
return obj == null;
|
||||
}
|
||||
|
||||
public static boolean isNotNull(Object obj) {
|
||||
return !isNull(obj);
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Object obj) {
|
||||
if (isNull(obj)) return true;
|
||||
else if (obj instanceof Collection<?> collection) return collection.isEmpty();
|
||||
else if (obj instanceof Map<?, ?> map) return map.isEmpty();
|
||||
else if (obj instanceof CharSequence sequence) return sequence.isEmpty();
|
||||
else if (obj instanceof Object[] 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 int[] 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 double[] 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 Optional<?> optional) return optional.isEmpty();
|
||||
else return false;
|
||||
}
|
||||
|
||||
public static boolean isNotEmpty(Object obj) {
|
||||
return !isEmpty(obj);
|
||||
}
|
||||
|
||||
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
||||
return isNull(object) ? defaultValue : object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lanyuanxiaoyao.service.template.repository;
|
||||
|
||||
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface SimpleRepository<E, ID> extends FenixJpaRepository<E, ID>, FenixJpaSpecificationExecutor<E>, QueryByExampleExecutor<E> {
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lanyuanxiaoyao.service.template.service;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.Query;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
/**
|
||||
* @author lanyuanxiaoyao
|
||||
* @date 2024-11-28
|
||||
*/
|
||||
public interface SimpleService<ENTITY extends SimpleEntity> {
|
||||
Long save(ENTITY entity) throws Exception;
|
||||
|
||||
Long count() throws Exception;
|
||||
|
||||
List<ENTITY> list() throws Exception;
|
||||
|
||||
List<ENTITY> list(Set<Long> ids) throws Exception;
|
||||
|
||||
Page<ENTITY> list(Query query) throws Exception;
|
||||
|
||||
Optional<ENTITY> detailOptional(Long id) throws Exception;
|
||||
|
||||
ENTITY detail(Long id) throws Exception;
|
||||
|
||||
ENTITY detailOrThrow(Long id) throws Exception;
|
||||
|
||||
ENTITY detailOrNull(Long id) throws Exception;
|
||||
|
||||
void remove(Long id) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
package com.lanyuanxiaoyao.service.template.service;
|
||||
|
||||
import com.lanyuanxiaoyao.service.template.controller.Query;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import com.lanyuanxiaoyao.service.template.helper.ObjectHelper;
|
||||
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Path;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implements SimpleService<ENTITY> {
|
||||
private static final Integer DEFAULT_PAGE_INDEX = 1;
|
||||
private static final Integer DEFAULT_PAGE_SIZE = 10;
|
||||
protected final SimpleRepository<ENTITY, Long> repository;
|
||||
|
||||
public SimpleServiceSupport(SimpleRepository<ENTITY, Long> repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Throwable.class)
|
||||
@Override
|
||||
public Long save(ENTITY entity) {
|
||||
if (!ObjectHelper.isNull(entity.getId())) {
|
||||
var id = entity.getId();
|
||||
var targetEntity = repository.findById(entity.getId()).orElseThrow(() -> new IdNotFoundException(id));
|
||||
BeanUtils.copyProperties(entity, targetEntity, "id", "created_time", "modified_time");
|
||||
entity = targetEntity;
|
||||
}
|
||||
entity = repository.save(entity);
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long count() {
|
||||
return repository.count(
|
||||
(root, query, builder) ->
|
||||
builder.and(
|
||||
listPredicate(root, query, builder)
|
||||
.stream()
|
||||
.filter(ObjectHelper::isNotNull)
|
||||
.toArray(Predicate[]::new)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ENTITY> list() {
|
||||
return repository.findAll(
|
||||
(root, query, builder) ->
|
||||
builder.and(
|
||||
listPredicate(root, query, builder)
|
||||
.stream()
|
||||
.filter(ObjectHelper::isNotNull)
|
||||
.toArray(Predicate[]::new)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ENTITY> list(Set<Long> ids) {
|
||||
return repository.findAll(
|
||||
(root, query, builder) -> {
|
||||
var predicates = listPredicate(root, query, builder);
|
||||
predicates.add(builder.in(root.get("id")).value(ids));
|
||||
return builder.and(predicates.stream().filter(ObjectHelper::isNotNull).toArray(Predicate[]::new));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private <Y> Path<Y> column(Root<ENTITY> root, String column) {
|
||||
if (ObjectHelper.isEmpty(column)) {
|
||||
throw new IllegalArgumentException("Column cannot be blank");
|
||||
}
|
||||
String[] columns = column.split("/");
|
||||
Path<Y> path = root.get(columns[0]);
|
||||
for (int i = 1; i < columns.length; i++) {
|
||||
path = path.get(columns[i]);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private <Y> Object value(Path<Y> column, Object value) {
|
||||
Class<?> javaType = column.getJavaType();
|
||||
if (javaType.isEnum()) {
|
||||
return Enum.valueOf((Class<Enum>) javaType, (String) value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected List<Predicate> queryPredicates(Query.Queryable queryable, Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
if (ObjectHelper.isNull(queryable)) {
|
||||
return predicates;
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNullEqual())) {
|
||||
queryable.getNullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotNullEqual())) {
|
||||
queryable.getNotNullEqual().forEach(column -> predicates.add(builder.isNull(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getEmpty())) {
|
||||
queryable.getEmpty().forEach(column -> predicates.add(builder.isEmpty(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotEmpty())) {
|
||||
queryable.getNotEmpty().forEach(column -> predicates.add(builder.isNotEmpty(column(root, column))));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getEqual())) {
|
||||
queryable.getEqual().forEach((column, value) -> {
|
||||
Path<Object> path = column(root, column);
|
||||
predicates.add(builder.equal(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotEqual())) {
|
||||
queryable.getEqual().forEach((column, value) -> {
|
||||
Path<Object> path = column(root, column);
|
||||
predicates.add(builder.notEqual(path, value(path, value)));
|
||||
});
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getLike())) {
|
||||
queryable.getLike().forEach((column, value) -> predicates.add(builder.like(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotLike())) {
|
||||
queryable.getNotLike().forEach((column, value) -> predicates.add(builder.notLike(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getGreat())) {
|
||||
queryable.getGreat().forEach((column, value) -> predicates.add(builder.greaterThan(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getLess())) {
|
||||
queryable.getLess().forEach((column, value) -> predicates.add(builder.lessThan(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getGreatEqual())) {
|
||||
queryable.getGreatEqual().forEach((column, value) -> predicates.add(builder.greaterThanOrEqualTo(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getLessEqual())) {
|
||||
queryable.getLessEqual().forEach((column, value) -> predicates.add(builder.lessThanOrEqualTo(column(root, column), value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getIn())) {
|
||||
queryable.getIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value)));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotIn())) {
|
||||
queryable.getNotIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value).not()));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getBetween())) {
|
||||
queryable.getBetween().forEach((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
|
||||
}
|
||||
if (ObjectHelper.isNotEmpty(queryable.getNotBetween())) {
|
||||
queryable.getNotBetween().forEach((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
|
||||
}
|
||||
return predicates;
|
||||
}
|
||||
|
||||
protected List<Predicate> listPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ENTITY> list(Query listQuery) {
|
||||
PageRequest pageRequest = PageRequest.of(DEFAULT_PAGE_INDEX - 1, DEFAULT_PAGE_SIZE, Sort.by("created_time").descending());
|
||||
if (ObjectHelper.isNotNull(listQuery.getPage())) {
|
||||
pageRequest = PageRequest.of(
|
||||
ObjectHelper.defaultIfNull(listQuery.getPage().getIndex(), DEFAULT_PAGE_INDEX) - 1,
|
||||
ObjectHelper.defaultIfNull(listQuery.getPage().getSize(), DEFAULT_PAGE_SIZE),
|
||||
Sort.by("create_time").descending()
|
||||
);
|
||||
}
|
||||
return repository.findAll(
|
||||
(root, query, builder) -> {
|
||||
var predicates = listPredicate(root, query, builder);
|
||||
predicates.addAll(queryPredicates(listQuery.getQuery(), root, query, builder));
|
||||
return builder.and(predicates.stream().filter(ObjectHelper::isNotNull).toArray(Predicate[]::new));
|
||||
},
|
||||
pageRequest
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ENTITY> detailOptional(Long id) {
|
||||
if (ObjectHelper.isNull(id)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return repository.findOne(
|
||||
(root, query, builder) -> {
|
||||
var predicates = listPredicate(root, query, builder);
|
||||
predicates.add(builder.equal(root.get("id"), id));
|
||||
return builder.and(predicates.stream().filter(ObjectHelper::isNotNull).toArray(Predicate[]::new));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ENTITY detail(Long id) {
|
||||
return detailOrNull(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ENTITY detailOrThrow(Long id) {
|
||||
return detailOptional(id).orElseThrow(() -> new IdNotFoundException(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ENTITY detailOrNull(Long id) {
|
||||
return detailOptional(id).orElse(null);
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = Throwable.class)
|
||||
@Override
|
||||
public void remove(Long id) {
|
||||
if (ObjectHelper.isNotNull(id)) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class IdNotFoundException extends RuntimeException {
|
||||
public IdNotFoundException() {
|
||||
super("资源不存在");
|
||||
}
|
||||
|
||||
public IdNotFoundException(Long id) {
|
||||
super("ID为%d的资源不存在".formatted(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user