diff --git a/.gitignore b/.gitignore index 2f40472..ea4dab9 100644 --- a/.gitignore +++ b/.gitignore @@ -133,4 +133,6 @@ Network Trash Folder Temporary Items .apdisk .opencode +.claude +.kilocode openspec/changes/archive \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d53ecaf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 34fa768..de80097 100644 --- a/pom.xml +++ b/pom.xml @@ -11,11 +11,7 @@ spring-boot-service-template-common - spring-boot-service-template-database/spring-boot-service-template-database-common - spring-boot-service-template-database/spring-boot-service-template-database-common-test - spring-boot-service-template-database/spring-boot-service-template-database-eq - spring-boot-service-template-database/spring-boot-service-template-database-jpa - spring-boot-service-template-database/spring-boot-service-template-database-xbatis + spring-boot-service-template-database @@ -31,8 +27,6 @@ 1.6.3 1.5.0 2.0.0 - 3.1.68 - 1.9.7-spring-boot4 5.8.43 @@ -57,12 +51,7 @@ com.lanyuanxiaoyao - spring-boot-service-template-database-common - ${project.version} - - - com.lanyuanxiaoyao - spring-boot-service-template-database-common-test + spring-boot-service-template-database ${project.version} @@ -117,22 +106,6 @@ ${hibernate.version} - - - cn.xbatis - xbatis-spring-boot-parent - ${xbatis.version} - pom - import - - - - - com.easy-query - sql-springboot4-starter - 3.1.68 - - org.jspecify jspecify diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/pom.xml b/spring-boot-service-template-database/pom.xml similarity index 88% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/pom.xml rename to spring-boot-service-template-database/pom.xml index e0d393b..845b57f 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/pom.xml +++ b/spring-boot-service-template-database/pom.xml @@ -9,12 +9,12 @@ 1.1.0-SNAPSHOT - spring-boot-service-template-database-jpa + spring-boot-service-template-database com.lanyuanxiaoyao - spring-boot-service-template-database-common + spring-boot-service-template-common @@ -35,16 +35,13 @@ io.github.openfeign.querydsl querydsl-jpa - org.hibernate.orm hibernate-ant - - com.lanyuanxiaoyao - spring-boot-service-template-database-common-test - test + org.mapstruct + mapstruct @@ -87,6 +84,11 @@ jakarta.persistence-api 3.2.0 + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + -Aquerydsl.entityAccessors=true diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/pom.xml b/spring-boot-service-template-database/spring-boot-service-template-database-common-test/pom.xml deleted file mode 100644 index 6be62e0..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - - com.lanyuanxiaoyao - spring-boot-service-template - 1.1.0-SNAPSHOT - - - spring-boot-service-template-database-common-test - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-jdbc - - - org.springframework.boot - spring-boot-starter-test - - - - org.mapstruct - mapstruct - compile - - - - com.github.gavlyukovskiy - p6spy-spring-boot-starter - - - - com.h2database - h2 - - - \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/java/com/lanyuanxiaoyao/service/template/database/common/test/AbstractTestApplication.java b/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/java/com/lanyuanxiaoyao/service/template/database/common/test/AbstractTestApplication.java deleted file mode 100644 index 5d1bc8d..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/java/com/lanyuanxiaoyao/service/template/database/common/test/AbstractTestApplication.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.common.test; - -import java.util.Map; -import java.util.Random; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.util.Assert; -import org.springframework.web.client.RestTemplate; -import tools.jackson.databind.JsonNode; -import tools.jackson.databind.ObjectMapper; - -@Slf4j -public class AbstractTestApplication { - private static final String BASE_URL = "http://localhost:2490"; - private static final RestTemplate REST_CLIENT = new RestTemplate(); - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final Random random = new Random(); - private static final String randomChars = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; - - protected void testCrud() { - formatLog("Save"); - var cid1 = saveItem("company", randomCompany("Apple")).get("data").asLong(); - var cid2 = saveItem("company", randomCompany()).get("data").asLong(); - var cid3 = saveItem("company", randomCompany()).get("data").asLong(); - - formatLog("List"); - assertListItems(listItems("company"), 3, 3); - - formatLog("Detail"); - var company1 = detailItem("company", cid1); - Assert.isTrue(cid1 == company1.at("/data/id").asLong(), "id错误"); - Assert.isTrue(company1.at("/data/name").asString("").startsWith("Apple"), "name错误"); - - var company2 = detailItem("company", cid2); - Assert.isTrue(cid2 == company2.at("/data/id").asLong(), "id错误"); - - var company3 = detailItem("company", cid3); - Assert.isTrue(cid3 == company3.at("/data/id").asLong(), "id错误"); - - formatLog("List Page"); - // language=JSON - var pageRequest = """ - { - "page": { - "index": 1, - "size": 2 - } - } - """; - assertListItems(listItems("company", pageRequest), 2, 3); - - formatLog("List Queryable"); - // language=JSON - var queryRequest = """ - { - "query": { - "notNullEqual": [ - "name" - ], - "equal": { - "name": "Apple" - }, - "like": { - "name": "Appl%" - }, - "contain": { - "name": "ple" - }, - "startWith": { - "name": "Appl" - }, - "endWith": { - "name": "le" - }, - "less": { - "members": 100 - }, - "greatEqual": { - "members": 0, - "createdTime": "2025-01-01 00:00:00" - }, - "inside": { - "name": [ - "Apple", - "Banana" - ] - }, - "between": { - "members": { - "start": 0, - "end": 100 - } - } - }, - "page": { - "index": 1, - "size": 2 - } - } - """; - assertListItems(listItems("company", queryRequest), 1, 1); - - formatLog("Clean"); - removeItem("company", cid1); - assertListItems(listItems("company"), 2, 2); - removeItem("company", cid2); - removeItem("company", cid3); - assertListItems(listItems("company"), 0, 0); - } - - protected void assertListItems(JsonNode node, int itemSizeTarget, int itemTotalTarget) { - var itemSize = node.at("/data/items").size(); - var itemTotal = node.at("/data/total").asLong(); - Assert.isTrue(itemSize == itemSizeTarget, "数量错误 (%d)".formatted(itemSize)); - Assert.isTrue(itemTotal == itemTotalTarget, "分页总数错误 (%d)".formatted(itemTotal)); - } - - protected void formatLog(String text) { - log.info("===== {} =====", text); - } - - protected Map randomCompany() { - return randomCompany(randomString(10)); - } - - protected Map randomCompany(String name) { - return Map.of( - "name", name, - "members", randomInt(100) - ); - } - - protected String randomString(String prefix, int length) { - return prefix + randomString(length); - } - - protected String randomString(int length) { - var builder = new StringBuilder(); - for (int i = 0; i < length; i++) { - builder.append(randomChars.charAt(random.nextInt(randomChars.length()))); - } - return builder.toString(); - } - - protected String randomChar(String base) { - return base.charAt(randomInt(base.length())) + ""; - } - - protected int randomInt(int bound) { - return random.nextInt(1, bound); - } - - protected double randomDouble(int bound) { - return random.nextDouble(1, bound); - } - - protected HttpHeaders headers() { - var headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - return headers; - } - - protected JsonNode saveItem(String path, Object body) { - var response = REST_CLIENT.postForEntity( - "%s/%s/save".formatted(BASE_URL, path), - new HttpEntity<>(body, headers()), - String.class - ); - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败"); - Assert.notNull(response.getBody(), "请求失败"); - return MAPPER.readTree(response.getBody()); - } - - protected JsonNode listItems(String path) { - var response = REST_CLIENT.getForEntity( - "%s/%s/list".formatted(BASE_URL, path), - String.class - ); - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败"); - Assert.notNull(response.getBody(), "请求失败"); - return MAPPER.readTree(response.getBody()); - } - - protected JsonNode listItems(String path, String query) { - var response = REST_CLIENT.postForEntity( - "%s/%s/list".formatted(BASE_URL, path), - new HttpEntity<>(query, headers()), - String.class - ); - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败"); - Assert.notNull(response.getBody(), "请求失败"); - return MAPPER.readTree(response.getBody()); - } - - protected JsonNode detailItem(String path, Long id) { - var response = REST_CLIENT.getForEntity( - "%s/%s/detail/%d".formatted(BASE_URL, path, id), - String.class - ); - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败"); - Assert.notNull(response.getBody(), "请求失败"); - return MAPPER.readTree(response.getBody()); - } - - protected void removeItem(String path, Long id) { - var response = REST_CLIENT.getForEntity( - "%s/%s/remove/%d".formatted(BASE_URL, path, id), - Void.class - ); - Assert.isTrue(response.getStatusCode().is2xxSuccessful(), "请求失败"); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/resources/application-test.yml b/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/resources/application-test.yml deleted file mode 100644 index 0b0fe18..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common-test/src/main/resources/application-test.yml +++ /dev/null @@ -1,12 +0,0 @@ -server: - port: 2490 -decorator: - datasource: - p6spy: - multiline: false - exclude-categories: - - commit - - result - - resultset - - rollback - log-format: "%(category)|%(executionTime)|%(sqlSingleLine)" \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/pom.xml b/spring-boot-service-template-database/spring-boot-service-template-database-common/pom.xml deleted file mode 100644 index 91e787a..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 4.0.0 - - com.lanyuanxiaoyao - spring-boot-service-template - 1.1.0-SNAPSHOT - - - spring-boot-service-template-database-common - - - - com.lanyuanxiaoyao - spring-boot-service-template-common - - - \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/pom.xml b/spring-boot-service-template-database/spring-boot-service-template-database-eq/pom.xml deleted file mode 100644 index f8a06a1..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - 4.0.0 - - com.lanyuanxiaoyao - spring-boot-service-template - 1.1.0-SNAPSHOT - - - spring-boot-service-template-database-eq - - - - com.lanyuanxiaoyao - spring-boot-service-template-database-common - - - - org.springframework.boot - spring-boot-starter-web - provided - - - - com.easy-query - sql-springboot4-starter - - - - com.lanyuanxiaoyao - spring-boot-service-template-database-common-test - test - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - package - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.projectlombok - lombok - - - com.easy-query - sql-processor - ${easy-query.version} - - - - - - - \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/controller/SimpleControllerSupport.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/controller/SimpleControllerSupport.java deleted file mode 100644 index 74fbab6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/controller/SimpleControllerSupport.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.controller; - -import com.easy.query.core.proxy.AbstractProxyEntity; -import com.easy.query.core.proxy.ProxyEntityAvailable; -import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.controller.SimpleController; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.eq.entity.SimpleEntity; -import com.lanyuanxiaoyao.service.template.database.eq.service.SimpleServiceSupport; -import java.util.function.Function; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.transaction.annotation.Transactional; -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; - -/** - * 简单控制器支持类,提供基础的CRUD操作实现 - *

- * 该类实现了基本的增删改查功能,通过泛型支持不同类型的数据转换。 - * 子类需要实现对应的Mapper函数来完成实体类与传输对象之间的转换。 - *

- * - *

设计特点

- *
    - *
  • 泛型设计,支持任意实体类型和数据转换
  • - *
  • 统一的异常处理和事务管理
  • - *
  • 支持条件查询、分页查询和详情查询
  • - *
  • 提供抽象的Mapper方法,便于子类实现数据转换逻辑
  • - *
- * - *

使用说明

- *

子类需要实现以下抽象方法:

- *
    - *
  • saveItemMapper(): 保存项到实体的转换函数
  • - *
  • listItemMapper(): 实体到列表项的转换函数
  • - *
  • detailItemMapper(): 实体到详情项的转换函数
  • - *
- * - * @param 实体类型,必须继承SimpleEntity - * @param 保存项类型 - * @param 列表项类型 - * @param 详情项类型 - */ -@Slf4j -@RequiredArgsConstructor -public abstract class SimpleControllerSupport, PROXY extends AbstractProxyEntity, SAVE_ITEM, LIST_ITEM, DETAIL_ITEM> implements SimpleController { - protected final SimpleServiceSupport service; - - /** - * 保存实体对象 - *

- * 将保存项转换为实体对象后保存,返回保存后的实体ID。 - * 支持新增和更新操作,通过事务保证数据一致性。 - *

- * - * @param item 需要保存的项 - * @return 返回保存后的实体ID响应对象,格式:{status: 0, message: "OK", data: 实体ID} - * @throws Exception 保存过程中可能抛出的异常 - */ - @Transactional(rollbackFor = Throwable.class) - @PostMapping(SAVE) - @Override - public GlobalResponse save(@RequestBody SAVE_ITEM item) throws Exception { - var mapper = saveItemMapper(); - return GlobalResponse.responseSuccess(service.save(mapper.apply(item))); - } - - /** - * 获取所有实体列表 - *

- * 查询所有记录,不带任何过滤条件,返回分页格式的数据。 - * 将实体对象转换为列表项对象后返回。 - *

- * - * @return 返回实体列表响应对象,格式:{status: 0, message: "OK", data: {items: [...], total: total}} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @GetMapping(LIST) - @Override - public GlobalResponse> list() throws Exception { - var mapper = listItemMapper(); - var result = service.list(); - return GlobalResponse.responseListData( - result - .stream() - .map(entity -> { - try { - return mapper.apply(entity); - } catch (Exception e) { - throw new RuntimeException(e); - } - }) - .toList(), - result.size() - ); - } - - /** - * 根据查询条件获取实体列表 - *

- * 支持复杂的查询条件、排序和分页,返回符合条件的数据。 - * 将实体对象转换为列表项对象后返回。 - *

- * - * @param query 查询条件对象,包含过滤条件、排序规则和分页信息 - * @return 返回符合条件的实体列表响应对象,格式:{status: 0, message: "OK", data: {items: [...], total: total}} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @PostMapping(LIST) - @Override - public GlobalResponse> list(@RequestBody Query query) throws Exception { - if (ObjectHelper.isNull(query)) { - return GlobalResponse.responseListData(); - } - var mapper = listItemMapper(); - var result = service.list(query); - return GlobalResponse.responseListData( - result.items() - .stream() - .map(entity -> { - try { - return mapper.apply(entity); - } catch (Exception e) { - throw new RuntimeException(e); - } - }) - .toList(), - result.total() - ); - } - - /** - * 根据ID获取实体详情 - *

- * 根据主键ID查询单条记录的详细信息,转换为详情项对象后返回。 - * 如果记录不存在则抛出异常。 - *

- * - * @param id 实体主键ID - * @return 返回实体详情响应对象,格式:{status: 0, message: "OK", data: 详情数据} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @GetMapping(DETAIL) - @Override - public GlobalResponse detail(@PathVariable("id") Long id) throws Exception { - var mapper = detailItemMapper(); - return GlobalResponse.responseSuccess(mapper.apply(service.detailOrThrow(id))); - } - - /** - * 根据ID删除实体对象 - *

- * 根据主键ID删除指定的记录,执行成功后返回成功响应。 - * 通过事务保证删除操作的一致性。 - *

- * - * @param id 需要删除的实体主键ID - * @return 返回删除结果响应对象,格式:{status: 0, message: "OK", data: null} - * @throws Exception 删除过程中可能抛出的异常 - */ - @Transactional(rollbackFor = Throwable.class) - @GetMapping(REMOVE) - @Override - public GlobalResponse remove(@PathVariable("id") Long id) throws Exception { - service.remove(id); - return GlobalResponse.responseSuccess(); - } - - /** - * 保存项映射器,将保存项转换为实体对象 - *

- * 子类需要实现此方法,定义保存项到实体的转换逻辑。 - *

- * - * @return Function 保存项到实体的转换函数 - */ - protected abstract Function saveItemMapper(); - - /** - * 列表项映射器,将实体对象转换为列表项 - *

- * 子类需要实现此方法,定义实体到列表项的转换逻辑。 - *

- * - * @return Function 实体到列表项的转换函数 - */ - protected abstract Function listItemMapper(); - - /** - * 详情项映射器,将实体对象转换为详情项 - *

- * 子类需要实现此方法,定义实体到详情项的转换逻辑。 - *

- * - * @return Function 实体到详情项的转换函数 - */ - protected abstract Function detailItemMapper(); - - public interface Mapper { - T map(S source) throws Exception; - } -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/IdOnlyEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/IdOnlyEntity.java deleted file mode 100644 index b25161d..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/IdOnlyEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import com.easy.query.core.annotation.Column; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString -@FieldNameConstants -public class IdOnlyEntity { - @Column(primaryKey = true, primaryKeyGenerator = SnowflakeIdGenerator.class) - private Long id; -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/LogicDeleteEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/LogicDeleteEntity.java deleted file mode 100644 index 29dcdd0..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/LogicDeleteEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import com.easy.query.core.annotation.LogicDelete; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString -@FieldNameConstants -public class LogicDeleteEntity extends IdOnlyEntity { - @LogicDelete - private Boolean deleted = false; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SimpleEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SimpleEntity.java deleted file mode 100644 index 24de424..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SimpleEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import java.time.LocalDateTime; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -public class SimpleEntity extends LogicDeleteEntity { - private LocalDateTime createdTime; - private LocalDateTime modifiedTime; -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SnowflakeIdGenerator.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SnowflakeIdGenerator.java deleted file mode 100644 index 388ed6f..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/entity/SnowflakeIdGenerator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import com.easy.query.core.basic.extension.generated.PrimaryKeyGenerator; -import com.lanyuanxiaoyao.service.template.database.common.helper.SnowflakeHelper; -import java.io.Serializable; -import org.springframework.stereotype.Component; - -@Component -public class SnowflakeIdGenerator implements PrimaryKeyGenerator { - @Override - public Serializable getPrimaryKey() { - return SnowflakeHelper.next(); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/service/SimpleServiceSupport.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/service/SimpleServiceSupport.java deleted file mode 100644 index 26d2015..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/main/java/com/lanyuanxiaoyao/service/template/database/eq/service/SimpleServiceSupport.java +++ /dev/null @@ -1,286 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.service; - -import com.easy.query.api.proxy.client.EasyEntityQuery; -import com.easy.query.core.enums.SQLExecuteStrategyEnum; -import com.easy.query.core.proxy.AbstractProxyEntity; -import com.easy.query.core.proxy.ProxyEntityAvailable; -import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.entity.Page; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.common.exception.IdNotFoundException; -import com.lanyuanxiaoyao.service.template.database.common.service.QueryParser; -import com.lanyuanxiaoyao.service.template.database.common.service.SimpleService; -import com.lanyuanxiaoyao.service.template.database.eq.entity.SimpleEntity; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.mapstruct.Named; -import org.springframework.transaction.annotation.Transactional; - -@Slf4j -@RequiredArgsConstructor -public abstract class SimpleServiceSupport, PROXY extends AbstractProxyEntity> implements SimpleService { - private static final int DEFAULT_PAGE_INDEX = 1; - private static final int DEFAULT_PAGE_SIZE = 10; - - protected final EasyEntityQuery entityQuery; - private final Class target; - - @Transactional(rollbackFor = Throwable.class) - @Override - public Long save(ENTITY entity) { - if (ObjectHelper.isNull(entity.getId())) { - entityQuery.insertable(entity).executeRows(); - } else { - entityQuery.updatable(entity) - .setSQLStrategy(SQLExecuteStrategyEnum.ONLY_NOT_NULL_COLUMNS) - .executeRows(); - } - return entity.getId(); - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void save(Iterable entities) { - var insertList = new ArrayList(); - var updateList = new ArrayList(); - for (var entity : entities) { - if (ObjectHelper.isNull(entity.getId())) { - insertList.add(entity); - } else { - updateList.add(entity); - } - } - if (ObjectHelper.isNotEmpty(insertList)) { - entityQuery.insertable(insertList).executeRows(); - } - if (ObjectHelper.isNotEmpty(updateList)) { - entityQuery.updatable(updateList) - .setSQLStrategy(SQLExecuteStrategyEnum.ONLY_NOT_NULL_COLUMNS) - .executeRows(); - } - } - - @Transactional(readOnly = true) - @Override - public Long count() { - return entityQuery.queryable(target).count(); - } - - @Transactional(readOnly = true) - @Override - public List list() { - return entityQuery.queryable(target).toList(); - } - - @Transactional(readOnly = true) - @Override - public List list(Set ids) { - if (ObjectHelper.isEmpty(ids)) { - return List.of(); - } - return entityQuery.queryable(target) - .whereByIds(ids) - .toList(); - } - - protected void commonPredicates(PROXY proxy) { - } - - @Transactional(readOnly = true) - @Override - public Page list(Query query) { - var index = DEFAULT_PAGE_INDEX; - var size = DEFAULT_PAGE_SIZE; - if (ObjectHelper.isNotNull(query.page())) { - index = Math.max(ObjectHelper.defaultIfNull(query.page().index(), DEFAULT_PAGE_INDEX), 1); - size = Math.max(ObjectHelper.defaultIfNull(query.page().size(), DEFAULT_PAGE_SIZE), 1); - } - - var result = entityQuery.queryable(target) - .where(this::commonPredicates) - .where(proxy -> new EqQueryParser(query.query(), proxy).build()) - .orderBy(ObjectHelper.isNotEmpty(query.sort()), proxy -> query.sort().forEach(sort -> proxy.anyColumn(sort.column()).orderBy(Query.Sortable.Direction.ASC.equals(sort.direction())))) - .toPageResult(index, size); - - return new Page<>(result.getData(), result.getTotal()); - } - - private Optional detailOptional(Long id) { - if (ObjectHelper.isNull(id)) { - return Optional.empty(); - } - return entityQuery.queryable(target) - .whereById(id) - .singleOptional(); - } - - @Named("detail") - @Transactional(readOnly = true) - @Override - public ENTITY detail(Long id) { - return detailOptional(id).orElse(null); - } - - @Named("detailOrThrow") - @Transactional(readOnly = true) - @Override - public ENTITY detailOrThrow(Long id) { - return detailOptional(id).orElseThrow(() -> new IdNotFoundException(id)); - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void remove(Long id) { - if (ObjectHelper.isNotNull(id)) { - entityQuery.deletable(target) - .whereById(id) - .allowDeleteStatement(true) - .executeRows(); - } - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void remove(Set ids) { - if (ObjectHelper.isNotEmpty(ids)) { - entityQuery.deletable(target) - .whereByIds(ids) - .allowDeleteStatement(true) - .executeRows(); - } - } - - private static final class EqQueryParser, PROXY extends AbstractProxyEntity> extends QueryParser { - public EqQueryParser(Query.Queryable queryable, PROXY container) { - super(queryable, container); - } - - @Override - protected void nullEqual(Query.Queryable queryable, PROXY proxy) { - queryable.nullEqual().forEach(column -> proxy.anyColumn(column).isNull()); - } - - @Override - protected void notNullEqual(Query.Queryable queryable, PROXY proxy) { - queryable.notNullEqual().forEach(column -> proxy.anyColumn(column).isNotNull()); - } - - @Override - protected void empty(Query.Queryable queryable, PROXY proxy) { - throw new UnsupportedOperationException(); - } - - @Override - protected void notEmpty(Query.Queryable queryable, PROXY proxy) { - throw new UnsupportedOperationException(); - } - - @Override - protected void equal(Query.Queryable queryable, PROXY proxy) { - queryable.equal().forEach((column, value) -> proxy.anyColumn(column).eq(value)); - } - - @Override - protected void notEqual(Query.Queryable queryable, PROXY proxy) { - queryable.notEqual().forEach((column, value) -> proxy.anyColumn(column).ne(value)); - } - - @Override - protected void like(Query.Queryable queryable, PROXY proxy) { - queryable.like().forEach((column, value) -> proxy.anyColumn(column).likeRaw(value)); - } - - @Override - protected void notLike(Query.Queryable queryable, PROXY proxy) { - queryable.notLike().forEach((column, value) -> proxy.anyColumn(column).notLikeRaw(value)); - } - - @Override - protected void contain(Query.Queryable queryable, PROXY proxy) { - queryable.contain().forEach((column, value) -> proxy.anyColumn(column).like(value)); - } - - @Override - protected void notContain(Query.Queryable queryable, PROXY proxy) { - queryable.notContain().forEach((column, value) -> proxy.anyColumn(column).notLike(value)); - } - - @Override - protected void startWith(Query.Queryable queryable, PROXY proxy) { - queryable.startWith().forEach((column, value) -> proxy.anyColumn(column).likeMatchLeft(value)); - } - - @Override - protected void notStartWith(Query.Queryable queryable, PROXY proxy) { - queryable.notStartWith().forEach((column, value) -> proxy.anyColumn(column).notLikeMatchLeft(value)); - } - - @Override - protected void endWith(Query.Queryable queryable, PROXY proxy) { - queryable.endWith().forEach((column, value) -> proxy.anyColumn(column).likeMatchRight(value)); - } - - @Override - protected void notEndWith(Query.Queryable queryable, PROXY proxy) { - queryable.notEndWith().forEach((column, value) -> proxy.anyColumn(column).notLikeMatchRight(value)); - } - - @Override - protected void great(Query.Queryable queryable, PROXY proxy) { - queryable.great().forEach((column, value) -> proxy.anyColumn(column).gt(value)); - } - - @Override - protected void less(Query.Queryable queryable, PROXY proxy) { - queryable.less().forEach((column, value) -> proxy.anyColumn(column).lt(value)); - } - - @Override - protected void greatEqual(Query.Queryable queryable, PROXY proxy) { - queryable.greatEqual().forEach((column, value) -> proxy.anyColumn(column).ge(value)); - } - - @Override - protected void lessEqual(Query.Queryable queryable, PROXY proxy) { - queryable.lessEqual().forEach((column, value) -> proxy.anyColumn(column).le(value)); - } - - @Override - protected void inside(Query.Queryable queryable, PROXY proxy) { - queryable.inside() - .entrySet() - .stream() - .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) - .forEach(entry -> proxy.anyColumn(entry.getKey()).in(entry.getValue())); - } - - @Override - protected void notInside(Query.Queryable queryable, PROXY proxy) { - queryable.notInside() - .entrySet() - .stream() - .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) - .forEach(entry -> proxy.anyColumn(entry.getKey()).notIn(entry.getValue())); - } - - @Override - protected void between(Query.Queryable queryable, PROXY proxy) { - queryable.between().forEach((column, value) -> { - proxy.anyColumn(column).gt(value.start()); - proxy.anyColumn(column).le(value.end()); - }); - } - - @Override - protected void notBetween(Query.Queryable queryable, PROXY proxy) { - queryable.between().forEach((column, value) -> { - proxy.anyColumn(column).le(value.start()); - proxy.anyColumn(column).gt(value.end()); - }); - } - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/initial.sql b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/initial.sql deleted file mode 100644 index 8cac5b1..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/initial.sql +++ /dev/null @@ -1,20 +0,0 @@ -create table if not exists Company -( - id bigint primary key, - name varchar(255) not null, - members int not null, - created_time timestamp not null default current_timestamp(), - modified_time timestamp not null default current_timestamp() on update current_timestamp(), - deleted tinyint not null default false -); - -create table if not exists Employee -( - id bigint primary key, - name varchar(255) not null, - age int not null, - company_id bigint not null, - created_time timestamp not null default current_timestamp(), - modified_time timestamp not null default current_timestamp() on update current_timestamp(), - deleted tinyint not null default false -); diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/TestApplication.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/TestApplication.java deleted file mode 100644 index 9fd80e6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/TestApplication.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq; - -import com.easy.query.api.proxy.client.EasyEntityQuery; -import com.lanyuanxiaoyao.service.template.database.common.test.AbstractTestApplication; -import com.lanyuanxiaoyao.service.template.database.eq.entity.Company; -import com.lanyuanxiaoyao.service.template.database.eq.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.EmployeeProxy; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.util.Assert; - -@Slf4j -@RequiredArgsConstructor -@SpringBootApplication -public class TestApplication extends AbstractTestApplication { - private final EasyEntityQuery entityQuery; - - public static void main(String[] args) { - SpringApplication.run(TestApplication.class, args); - } - - @EventListener(ApplicationReadyEvent.class) - public void runTests() { - testCrud(); - testDelete(); - testQuery(); - - System.exit(0); - } - - private void testDelete() { - formatLog("Delete"); - saveItem("company", randomCompany()); - saveItem("company", randomCompany()); - entityQuery.deletable(Company.class) - .where(proxy -> proxy.id().isNotNull()) - .allowDeleteStatement(true) - .executeRows(); - } - - private void testQuery() { - formatLog("Added"); - var company1 = Company.builder().name(randomString(5)).members(randomInt(100)).build(); - entityQuery.insertable(company1).executeRows(); - var company2 = Company.builder().name(randomString(5)).members(randomInt(100)).build(); - entityQuery.insertable(company2).executeRows(); - var employee1 = Employee.builder().name("Tom").age(randomInt(100)).companyId(company1.getId()).build(); - entityQuery.insertable(employee1).executeRows(); - var employee2 = Employee.builder().name(randomString(10)).age(randomInt(100)).companyId(company2.getId()).build(); - entityQuery.insertable(employee2).executeRows(); - - formatLog("Query"); - var employees1 = entityQuery.queryable(Employee.class) - .include(EmployeeProxy::company) - .where(proxy -> { - proxy.name().isNotNull(); - proxy.name().eq("Tom"); - proxy.name().startsWith("To"); - proxy.name().endsWith("om"); - proxy.age().lt(200); - proxy.age().gt(0); - proxy.name().in(List.of("Tom", "Mike")); - }) - .toList(); - Assert.isTrue(employees1.size() == 1, "查询数量错误"); - - formatLog("Clean"); - entityQuery.deletable(Company.class).where(proxy -> proxy.id().isNotNull()).executeRows(); - entityQuery.deletable(Employee.class).where(proxy -> proxy.id().isNotNull()).executeRows(); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/controller/CompanyController.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/controller/CompanyController.java deleted file mode 100644 index fa30e37..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/controller/CompanyController.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.controller; - -import com.lanyuanxiaoyao.service.template.database.eq.entity.Company; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.CompanyProxy; -import com.lanyuanxiaoyao.service.template.database.eq.service.CompanyService; -import java.time.LocalDateTime; -import java.util.function.Function; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Slf4j -@RestController -@RequestMapping("company") -public class CompanyController extends SimpleControllerSupport { - public CompanyController(CompanyService service) { - super(service); - } - - @Override - protected Function saveItemMapper() { - return item -> { - var company = new Company(); - company.setId(item.id()); - company.setName(item.name()); - company.setMembers(item.members()); - return company; - }; - } - - @Override - protected Function listItemMapper() { - return company -> new ListItem( - company.getId(), - company.getName(), - company.getMembers() - ); - } - - @Override - protected Function detailItemMapper() { - return company -> new DetailItem( - company.getId(), - company.getName(), - company.getMembers(), - company.getCreatedTime(), - company.getModifiedTime() - ); - } - - public record SaveItem( - Long id, - String name, - Integer members - ) { - } - - public record ListItem( - Long id, - String name, - Integer members - ) { - } - - public record DetailItem( - Long id, - String name, - Integer members, - LocalDateTime createdTime, - LocalDateTime modifiedTime - ) { - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Company.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Company.java deleted file mode 100644 index 5d7a0db..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Company.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import com.easy.query.core.annotation.EntityProxy; -import com.easy.query.core.annotation.Navigate; -import com.easy.query.core.annotation.Table; -import com.easy.query.core.enums.RelationTypeEnum; -import com.easy.query.core.proxy.ProxyEntityAvailable; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.CompanyProxy; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Table -@EntityProxy -public class Company extends SimpleEntity implements ProxyEntityAvailable { - private String name; - private Integer members; - - @Navigate(value = RelationTypeEnum.OneToMany, selfProperty = {"id"}, targetProperty = {"companyId"}) - private List employees; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Employee.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Employee.java deleted file mode 100644 index 25248f9..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/entity/Employee.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.entity; - -import com.easy.query.core.annotation.EntityProxy; -import com.easy.query.core.annotation.Navigate; -import com.easy.query.core.annotation.Table; -import com.easy.query.core.enums.RelationTypeEnum; -import com.easy.query.core.proxy.ProxyEntityAvailable; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.EmployeeProxy; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Table -@EntityProxy -public class Employee extends SimpleEntity implements ProxyEntityAvailable { - private String name; - private Integer age; - private Long companyId; - - @Navigate(value = RelationTypeEnum.OneToOne, selfProperty = {"companyId"}, targetProperty = {"id"}) - private Company company; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/CompanyService.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/CompanyService.java deleted file mode 100644 index 0e87184..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/CompanyService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.service; - -import com.easy.query.api.proxy.client.EasyEntityQuery; -import com.lanyuanxiaoyao.service.template.database.eq.entity.Company; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.CompanyProxy; -import org.springframework.stereotype.Service; - -@Service -public class CompanyService extends SimpleServiceSupport { - public CompanyService(EasyEntityQuery entityQuery) { - super(entityQuery, Company.class); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/EmployeeService.java b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/EmployeeService.java deleted file mode 100644 index 454aa09..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/java/com/lanyuanxiaoyao/service/template/database/eq/service/EmployeeService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.eq.service; - -import com.easy.query.api.proxy.client.EasyEntityQuery; -import com.lanyuanxiaoyao.service.template.database.eq.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.eq.entity.proxy.EmployeeProxy; -import org.springframework.stereotype.Service; - -@Service -public class EmployeeService extends SimpleServiceSupport { - public EmployeeService(EasyEntityQuery entityQuery) { - super(entityQuery, Employee.class); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/resources/application.yml b/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/resources/application.yml deleted file mode 100644 index e8dfe8f..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/resources/application.yml +++ /dev/null @@ -1,13 +0,0 @@ -spring: - profiles: - include: test - datasource: - url: "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL;DATABASE_TO_LOWER=TRUE;INIT=runscript from '/Users/lanyuanxiaoyao/Project/IdeaProjects/spring-boot-service-template/spring-boot-service-template-database/spring-boot-service-template-database-eq/src/test/initial.sql'" - username: test - password: test - driver-class-name: org.h2.Driver -easy-query: - database: mysql - name-conversion: underlined - print-sql: false - print-nav-sql: false diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/TestApplication.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/TestApplication.java deleted file mode 100644 index 1d3146f..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/TestApplication.java +++ /dev/null @@ -1,1394 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa; - -import com.blinkfox.fenix.EnableFenix; -import com.lanyuanxiaoyao.service.template.database.common.test.AbstractTestApplication; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Address; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Address_; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company_; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee_; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.QEmployee; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Skill; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Skill_; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.CompanyRepository; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.EmployeeRepository; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.ReportRepository; -import com.querydsl.core.types.dsl.CaseBuilder; -import com.querydsl.jpa.impl.JPAQueryFactory; -import jakarta.persistence.EntityManager; -import java.math.BigDecimal; -import java.util.List; -import java.util.Map; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; - -@Slf4j -@RequiredArgsConstructor -@SpringBootApplication -@EnableFenix -@EnableJpaAuditing -@Transactional -public class TestApplication extends AbstractTestApplication { - private final CompanyRepository companyRepository; - private final EmployeeRepository employeeRepository; - private final ReportRepository reportRepository; - private final EntityManager manager; - private final JPAQueryFactory factory; - - public static void main(String[] args) { - SpringApplication.run(TestApplication.class, args); - } - - @EventListener(ApplicationReadyEvent.class) - public void runTests() { - testCrud(); - testDelete(); - testQuery(); - testMethodQuery(); - - System.exit(0); - } - - private void testDelete() { - formatLog("Delete JPA"); - saveItem("company", randomCompany()); - saveItem("company", randomCompany()); - companyRepository.deleteAll(); - - formatLog("Delete JPA Batch"); - saveItem("company", randomCompany()); - saveItem("company", randomCompany()); - companyRepository.deleteAllInBatch(); - - formatLog("Delete JPA by id"); - var cid1 = saveItem("company", randomCompany()).get("data").asLong(); - var cid2 = saveItem("company", randomCompany()).get("data").asLong(); - companyRepository.deleteAllById(List.of(cid1, cid2)); - - formatLog("Delete Fenix by id"); - cid1 = saveItem("company", randomCompany()).get("data").asLong(); - cid2 = saveItem("company", randomCompany()).get("data").asLong(); - companyRepository.deleteByIds(List.of(cid1, cid2)); - - formatLog("Delete Fenix Batch by id"); - cid1 = saveItem("company", randomCompany()).get("data").asLong(); - cid2 = saveItem("company", randomCompany()).get("data").asLong(); - companyRepository.deleteBatchByIds(List.of(cid1, cid2)); - } - - private void testQuery() { - // ==================== 测试阶段 1: 准备测试数据 ==================== - formatLog("阶段 1: 准备测试数据"); - var company1 = companyRepository.save(Company.builder().name("TechCorp").members(100).build()); - var company2 = companyRepository.save(Company.builder().name("DataInc").members(50).build()); - var company3 = companyRepository.save(Company.builder().name("CloudSys").members(150).build()); - - // 准备 Skills 数据 - var skill1 = Skill.builder().name("Java").description("Java 编程语言").build(); - var skill2 = Skill.builder().name("Python").description("Python 编程语言").build(); - var skill3 = Skill.builder().name("Spring").description("Spring 框架").build(); - var skill4 = Skill.builder().name("MySQL").description("MySQL 数据库").build(); - - employeeRepository.save(Employee.builder() - .name("Alice").age(30).role(Employee.Role.ADMIN).code("E001") - .salary(new BigDecimal("50000.00")).bonus(new BigDecimal("5000.00")) - .active(true).company(company1) - .address(Address.builder().street("Main St").city("Beijing").state("Beijing").zipCode("100000").country("China").build()) - .skills(Set.of(skill1, skill3)) - .hobbies(List.of("Reading", "Swimming")) - .properties(Map.of("department", "Engineering", "level", "Senior")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "alice@example.com")) - .build()); - - employeeRepository.save(Employee.builder() - .name("Bob").age(25).role(Employee.Role.USER).code("E002") - .salary(new BigDecimal("40000.00")).bonus(new BigDecimal("4000.00")) - .active(true).company(company2) - .address(Address.builder().street("Oak Ave").city("Shanghai").state("Shanghai").zipCode("200000").country("China").build()) - .skills(Set.of(skill2)) - .hobbies(List.of("Gaming")) - .properties(Map.of("department", "Marketing", "level", "Junior")) - .connections(Map.of(Employee.ConnectionType.PHONE, "1234567890")) - .build()); - - employeeRepository.save(Employee.builder() - .name("Charlie").age(35).role(Employee.Role.ADMIN).code("E003") - .salary(new BigDecimal("60000.00")).bonus(new BigDecimal("6000.00")) - .active(false).company(company1) - .address(Address.builder().street("Pine Rd").city("Shenzhen").state("Guangdong").zipCode("518000").country("China").build()) - .skills(Set.of(skill1, skill2, skill3)) - .hobbies(List.of("Reading", "Gaming", "Music")) - .properties(Map.of("department", "Engineering", "level", "Lead")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "charlie@example.com", Employee.ConnectionType.PHONE, "0987654321")) - .build()); - - employeeRepository.save(Employee.builder() - .name("David").age(28).role(Employee.Role.USER).code("E004") - .salary(new BigDecimal("45000.00")).bonus(null) - .active(true).company(company3) - .address(Address.builder().street("Elm Ln").city("Guangzhou").state("Guangdong").zipCode("510000").country("China").build()) - .skills(Set.of(skill4)) - .hobbies(List.of()) - .properties(Map.of()) - .connections(Map.of()) - .build()); - - employeeRepository.save(Employee.builder() - .name("Alice Smith").age(32).role(Employee.Role.USER).code("E005") - .salary(new BigDecimal("55000.00")).bonus(new BigDecimal("5500.00")) - .active(true).company(company2) - .address(Address.builder().street("Maple Dr").city("Hangzhou").state("Zhejiang").zipCode("310000").country("China").build()) - .skills(Set.of(skill1, skill4)) - .hobbies(List.of("Swimming", "Music")) - .properties(Map.of("department", "Sales", "level", "Middle")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "alicesmith@example.com")) - .build()); - - // ==================== 测试阶段 2: 基本比较操作符查询 ==================== - formatLog("阶段 2: 基本比较操作符查询"); - log.info("查询条件: 姓名='Bob' AND 角色!=ADMIN AND 年龄>20 AND 年龄<30 AND 薪资>=40000 AND 薪资<=45000"); - - formatLog("2.1 JPA Specification"); - // 查找姓名为"Bob"、角色不是ADMIN、年龄在20-30之间、薪资在40000-45000之间的员工 - var result1_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.equal(root.get(Employee_.name), "Bob"), - cb.notEqual(root.get(Employee_.role), Employee.Role.ADMIN), - cb.greaterThan(root.get(Employee_.age), 20), - cb.lessThan(root.get(Employee_.age), 30), - cb.greaterThanOrEqualTo(root.get(Employee_.salary), new BigDecimal("40000.00")), - cb.lessThanOrEqualTo(root.get(Employee_.salary), new BigDecimal("45000.00")) - )); - Assert.isTrue(result1_jpa.size() == 1, "JPA Specification 查询失败 (%d)".formatted(result1_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result1_jpa.size()); - - formatLog("2.2 Fenix"); - var result1_fenix = employeeRepository.findAll( - builder -> builder.andEquals(Employee.Fields.name, "Bob") - .andNotEquals(Employee.Fields.role, Employee.Role.ADMIN) - .andGreaterThan(Employee.Fields.age, 20) - .andLessThan(Employee.Fields.age, 30) - .andGreaterThanEqual(Employee.Fields.salary, new BigDecimal("40000.00")) - .andLessThanEqual(Employee.Fields.salary, new BigDecimal("45000.00")) - .build() - ); - Assert.isTrue(result1_fenix.size() == 1, "Fenix 查询失败 (%d)".formatted(result1_fenix.size())); - log.info("Fenix 结果: {} 条记录", result1_fenix.size()); - - formatLog("2.3 QueryDSL"); - var result1_querydsl = employeeRepository.findAll( - QEmployee.employee.name.eq("Bob") - .and(QEmployee.employee.role.ne(Employee.Role.ADMIN)) - .and(QEmployee.employee.age.gt(20)) - .and(QEmployee.employee.age.lt(30)) - .and(QEmployee.employee.salary.goe(new BigDecimal("40000.00"))) - .and(QEmployee.employee.salary.loe(new BigDecimal("45000.00"))) - ); - Assert.isTrue(result1_querydsl.size() == 1, "QueryDSL 查询失败 (%d)".formatted(result1_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result1_querydsl.size()); - - formatLog("2.4 HQL"); - var result1_hql = manager.createQuery( - """ - from Employee employee - where employee.name = 'Bob' - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN - and employee.age > 20 - and employee.age < 30 - and employee.salary >= 40000.00 - and employee.salary <= 45000.00 - """, - Employee.class - ).getResultList(); - Assert.isTrue(result1_hql.size() == 1, "HQL 查询失败 (%d)".formatted(result1_hql.size())); - log.info("HQL 结果: {} 条记录", result1_hql.size()); - - // ==================== 测试阶段 3: 区间和集合操作符查询 ==================== - formatLog("阶段 3: 区间和集合操作符查询"); - log.info("查询条件: 年龄 BETWEEN 25-30 AND NOT BETWEEN 40-50 AND 年龄 IN (25,30,35) AND 角色 IN (USER,ADMIN) AND 姓名 NOT IN (Charlie,David)"); - - formatLog("3.1 JPA Specification"); - // 查找年龄在25-30之间、年龄不在40-50之间、年龄在25/30/35中、角色是USER或ADMIN、姓名不在Charlie/David中的员工 - var result2_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.between(root.get(Employee_.age), 25, 30), - cb.between(root.get(Employee_.age), 40, 50).not(), - root.get(Employee_.age).in(25, 30, 35), - root.get(Employee_.role).in(Employee.Role.USER, Employee.Role.ADMIN), - cb.not(root.get(Employee_.name).in("Charlie", "David")), - root.get(Employee_.name).in("Charlie", "David").not() - )); - Assert.isTrue(result2_jpa.size() == 2, "JPA Specification 查询失败 (%d)".formatted(result2_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result2_jpa.size()); - - formatLog("3.2 Fenix"); - var result2_fenix = employeeRepository.findAll( - builder -> builder.andBetween(Employee.Fields.age, 25, 30) - .andNotBetween(Employee.Fields.age, 40, 50) - .andIn(Employee.Fields.age, List.of(25, 30, 35)) - .andIn(Employee.Fields.role, List.of(Employee.Role.USER, Employee.Role.ADMIN)) - .andNotIn(Employee.Fields.name, List.of("Charlie", "David")) - .build() - ); - Assert.isTrue(result2_fenix.size() == 2, "Fenix 查询失败 (%d)".formatted(result2_fenix.size())); - log.info("Fenix 结果: {} 条记录", result2_fenix.size()); - - formatLog("3.3 QueryDSL"); - var result2_querydsl = employeeRepository.findAll( - QEmployee.employee.age.between(25, 30) - .and(QEmployee.employee.age.between(40, 50).not()) - .and(QEmployee.employee.age.in(25, 30, 35)) - .and(QEmployee.employee.role.in(Employee.Role.USER, Employee.Role.ADMIN)) - .and(QEmployee.employee.name.in(List.of("Charlie", "David")).not()) - ); - Assert.isTrue(result2_querydsl.size() == 2, "QueryDSL 查询失败 (%d)".formatted(result2_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result2_querydsl.size()); - - formatLog("3.4 HQL"); - var result2_hql = manager.createQuery( - """ - from Employee employee - where employee.age between 25 and 30 - and not (employee.age between 40 and 50) - and employee.age in (25, 30, 35) - and employee.role in (com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.USER, com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN) - and employee.name not in ('Charlie', 'David') - """, - Employee.class - ).getResultList(); - Assert.isTrue(result2_hql.size() == 2, "HQL 查询失败 (%d)".formatted(result2_hql.size())); - log.info("HQL 结果: {} 条记录", result2_hql.size()); - - // ==================== 测试阶段 4: 字符串操作符查询 ==================== - formatLog("阶段 4: 字符串操作符查询"); - log.info("查询条件: 姓名 LIKE 'A%' AND NOT LIKE 'C%' AND LOWER(姓名) LIKE '%ali%' AND UPPER(姓名) LIKE '%ALI%' AND LENGTH(姓名)>4 AND LENGTH(姓名)<=10 AND SUBSTRING(姓名,1,3)='Ali'"); - - formatLog("4.1 JPA Specification"); - // 查找以A开头、不以C开头、包含"ali"(忽略大小写)、名称长度在4-10之间、前3个字符为"Ali"的员工 - var result3_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.like(root.get(Employee_.name), "A%"), - cb.notLike(root.get(Employee_.name), "C%"), - cb.like(cb.lower(root.get(Employee_.name)), "%ali%"), - cb.like(cb.upper(root.get(Employee_.name)), "%ALI%"), - cb.greaterThan(cb.length(root.get(Employee_.name)), 4), - cb.lessThanOrEqualTo(cb.length(root.get(Employee_.name)), 10), - cb.equal(cb.substring(root.get(Employee_.name), 0, 3), "Ali") - )); - Assert.isTrue(result3_jpa.size() == 1, "JPA Specification 查询失败 (%d)".formatted(result3_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result3_jpa.size()); - - formatLog("4.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持以下字符串操作符: - - cb.length() - 字符串长度函数 - - cb.substring() - 子字符串提取函数 - - cb.lower() / cb.upper() - 大小写转换函数 (不支持直接在条件中使用) - Fenix支持的部分实现:"""); - var result3_fenix = employeeRepository.findAll( - builder -> builder.andStartsWith(Employee.Fields.name, "A") - .andNotStartsWith(Employee.Fields.name, "C") - .build() - ); - log.info("Fenix 结果: {} 条记录(仅支持部分条件)", result3_fenix.size()); - - formatLog("4.3 QueryDSL"); - var result3_querydsl = employeeRepository.findAll( - QEmployee.employee.name.startsWith("A") - .and(QEmployee.employee.name.startsWith("C").not()) - .and(QEmployee.employee.name.toLowerCase().contains("ali")) - .and(QEmployee.employee.name.toUpperCase().contains("ALI")) - .and(QEmployee.employee.name.length().gt(4)) - .and(QEmployee.employee.name.length().loe(10)) - .and(QEmployee.employee.name.substring(0, 3).eq("Ali")) - ); - Assert.isTrue(result3_querydsl.size() == 1, "QueryDSL 查询失败 (%d)".formatted(result3_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result3_querydsl.size()); - - formatLog("4.4 HQL"); - var result3_hql = manager.createQuery( - """ - from Employee employee - where employee.name like 'A%' - and employee.name not like 'C%' - and lower(employee.name) like '%ali%' - and upper(employee.name) like '%ALI%' - and length(employee.name) > 4 - and length(employee.name) <= 10 - and substring(employee.name, 1, 3) = 'Ali' - """, - Employee.class - ).getResultList(); - Assert.isTrue(result3_hql.size() == 1, "HQL 查询失败 (%d)".formatted(result3_hql.size())); - log.info("HQL 结果: {} 条记录", result3_hql.size()); - - // ==================== 测试阶段 5: NULL 和布尔操作符查询 ==================== - formatLog("阶段 5: NULL 和布尔操作符查询"); - log.info("查询条件: active=true AND bonus IS NOT NULL AND code NOT IN ('E999')"); - - formatLog("5.1 JPA Specification"); - // 查找激活状态为true、bonus不为null、code不在E999中的员工 - var result4_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.isTrue(root.get(Employee_.active)), - cb.isNotNull(root.get(Employee_.bonus)), - cb.not(root.get(Employee_.code).in("E999")) - )); - Assert.isTrue(!result4_jpa.isEmpty(), "JPA Specification 查询失败 (%d)".formatted(result4_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result4_jpa.size()); - - formatLog("5.2 Fenix"); - var result4_fenix = employeeRepository.findAll( - builder -> builder.andEquals(Employee.Fields.active, true) - .andIsNotNull(Employee.Fields.bonus) - .andNotIn(Employee.Fields.code, List.of("E999")) - .build() - ); - Assert.isTrue(!result4_fenix.isEmpty(), "Fenix 查询失败 (%d)".formatted(result4_fenix.size())); - log.info("Fenix 结果: {} 条记录", result4_fenix.size()); - - formatLog("5.3 QueryDSL"); - var result4_querydsl = employeeRepository.findAll( - QEmployee.employee.active.isTrue() - .and(QEmployee.employee.bonus.isNotNull()) - .and(QEmployee.employee.code.in("E999").not()) - ); - Assert.isTrue(!result4_querydsl.isEmpty(), "QueryDSL 查询失败 (%d)".formatted(result4_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result4_querydsl.size()); - - formatLog("5.4 HQL"); - var result4_hql = manager.createQuery( - """ - from Employee employee - where employee.active is true - and employee.bonus is not null - and employee.code not in ('E999') - """, - Employee.class - ).getResultList(); - Assert.isTrue(!result4_hql.isEmpty(), "HQL 查询失败 (%d)".formatted(result4_hql.size())); - log.info("HQL 结果: {} 条记录", result4_hql.size()); - - // ==================== 测试阶段 6: 集合操作符查询 ==================== - formatLog("阶段 6: 集合操作符查询"); - log.info("查询条件: skills IS NOT EMPTY AND hobbies IS NOT EMPTY AND 'Reading' MEMBER OF hobbies AND 'Riding' NOT MEMBER OF hobbies AND SIZE(hobbies)>1 AND SIZE(skills)<4"); - - formatLog("6.1 JPA Specification"); - // 查找技能集合非空、爱好集合非空、包含"Reading"爱好、不包含"Riding"爱好、爱好数量大于1、技能数量小于4的员工 - var result5_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.isNotEmpty(root.get(Employee_.skills)), - cb.isEmpty(root.get(Employee_.hobbies)).not(), - cb.isMember("Reading", root.get(Employee_.hobbies)), - cb.isNotMember("Riding", root.get(Employee_.hobbies)), - cb.greaterThan(cb.size(root.get(Employee_.hobbies)), 1), - cb.lessThan(cb.size(root.get(Employee_.skills)), 4) - )); - Assert.isTrue(result5_jpa.size() == 2, "JPA Specification 查询失败 (%d)".formatted(result5_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result5_jpa.size()); - - formatLog("6.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持以下集合操作符: - - cb.isNotEmpty() / cb.isEmpty() - 集合非空/空判断 - - cb.isMember() / cb.isNotMember() - 集合成员判断 - - cb.size() - 集合大小函数 - 这些集合操作在JPA Criteria中需要复杂的join处理,Fenix当前不支持"""); - - formatLog("6.3 QueryDSL"); - var result5_querydsl = employeeRepository.findAll( - QEmployee.employee.skills.isNotEmpty() - .and(QEmployee.employee.hobbies.isNotEmpty()) - .and(QEmployee.employee.hobbies.contains("Reading")) - .and(QEmployee.employee.hobbies.contains("Riding").not()) - .and(QEmployee.employee.hobbies.size().gt(1)) - .and(QEmployee.employee.skills.size().lt(4)) - ); - Assert.isTrue(result5_querydsl.size() == 2, "QueryDSL 查询失败 (%d)".formatted(result5_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result5_querydsl.size()); - - formatLog("6.4 HQL"); - var result5_hql = manager.createQuery( - """ - from Employee employee - where employee.skills is not empty - and employee.hobbies is not empty - and 'Reading' member of employee.hobbies - and 'Riding' not member of employee.hobbies - and size(employee.hobbies) > 1 - and size(employee.skills) < 4 - """, - Employee.class - ).getResultList(); - Assert.isTrue(result5_hql.size() == 2, "HQL 查询失败 (%d)".formatted(result5_hql.size())); - log.info("HQL 结果: {} 条记录", result5_hql.size()); - - // ==================== 测试阶段 7: 逻辑操作符查询 ==================== - formatLog("阶段 7: 逻辑操作符查询"); - log.info("查询条件: (姓名='Alice' OR 姓名='Bob') AND NOT (姓名='Charlie' OR 姓名='David')"); - - formatLog("7.1 JPA Specification"); - // 查找姓名为Alice或Bob、且姓名不为Charlie或David的员工 - var result6_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.or( - cb.equal(root.get(Employee_.name), "Alice"), - cb.equal(root.get(Employee_.name), "Bob") - ), - cb.not( - cb.or( - cb.equal(root.get(Employee_.name), "Charlie"), - cb.equal(root.get(Employee_.name), "David") - ) - ) - )); - Assert.isTrue(result6_jpa.size() == 2, "JPA Specification 查询失败 (%d)".formatted(result6_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result6_jpa.size()); - - formatLog("7.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持复杂的嵌套OR和NOT组合逻辑 - Fenix支持简单的orEquals,但不支持嵌套的or + not组合"""); - var result6_fenix = employeeRepository.findAll( - builder -> builder.orEquals(Employee.Fields.name, "Alice") - .orEquals(Employee.Fields.name, "Bob") - .andNotIn(Employee.Fields.name, List.of("Charlie", "David")) - .build() - ); - Assert.isTrue(result6_fenix.size() == 3, "Fenix 查询失败 (%d)".formatted(result6_fenix.size())); - log.info("Fenix 结果: {} 条记录(逻辑不完全等价)", result6_fenix.size()); - - formatLog("7.3 QueryDSL"); - var result6_querydsl = employeeRepository.findAll( - QEmployee.employee.name.eq("Alice").or(QEmployee.employee.name.eq("Bob")) - .and(QEmployee.employee.name.eq("Charlie").or(QEmployee.employee.name.eq("David")).not()) - ); - Assert.isTrue(result6_querydsl.size() == 2, "QueryDSL 查询失败 (%d)".formatted(result6_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result6_querydsl.size()); - - formatLog("7.4 HQL"); - var result6_hql = manager.createQuery( - """ - from Employee employee - where (employee.name = 'Alice' or employee.name = 'Bob') - and not (employee.name = 'Charlie' or employee.name = 'David') - """, - Employee.class - ).getResultList(); - Assert.isTrue(result6_hql.size() == 2, "HQL 查询失败 (%d)".formatted(result6_hql.size())); - log.info("HQL 结果: {} 条记录", result6_hql.size()); - - // ==================== 测试阶段 8: Specification 链式调用查询 ==================== - formatLog("阶段 8: Specification 链式调用查询"); - log.info("查询条件: active=true AND age>25 AND role!=ADMIN OR name='Charlie' AND name!='Alice Smith'"); - - formatLog("8.1 JPA Specification"); - // 链式组合:激活状态为true、年龄大于25、角色不是ADMIN、或姓名为Charlie、且姓名不为Alice Smith - var result7_jpa = employeeRepository.findAll( - Specification.where((root, query, cb) -> cb.isTrue(root.get(Employee_.active))) - .and((root, query, cb) -> cb.greaterThan(root.get(Employee_.age), 25)) - .and((root, query, cb) -> cb.notEqual(root.get(Employee_.role), Employee.Role.ADMIN)) - .or((root, query, cb) -> cb.equal(root.get(Employee_.name), "Charlie")) - .and((root, query, cb) -> cb.notEqual(root.get(Employee_.name), "Alice Smith")) - ); - Assert.isTrue(result7_jpa.size() == 2, "JPA Specification 链式调用失败 (%d)".formatted(result7_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result7_jpa.size()); - - formatLog("8.2 Fenix"); - var result7_fenix = employeeRepository.findAll( - builder -> builder.andEquals(Employee.Fields.active, true) - .andGreaterThan(Employee.Fields.age, 25) - .andNotEquals(Employee.Fields.role, Employee.Role.ADMIN) - .orEquals(Employee.Fields.name, "Charlie") - .andNotEquals(Employee.Fields.name, "Alice Smith") - .build() - ); - Assert.isTrue(result7_fenix.size() == 2, "Fenix 链式调用失败 (%d)".formatted(result7_fenix.size())); - log.info("Fenix 结果: {} 条记录", result7_fenix.size()); - - formatLog("8.3 QueryDSL"); - var result7_querydsl = employeeRepository.findAll( - QEmployee.employee.active.isTrue() - .and(QEmployee.employee.age.gt(25)) - .and(QEmployee.employee.role.ne(Employee.Role.ADMIN)) - .or(QEmployee.employee.name.eq("Charlie")) - .and(QEmployee.employee.name.ne("Alice Smith")) - ); - Assert.isTrue(result7_querydsl.size() == 2, "QueryDSL 链式调用失败 (%d)".formatted(result7_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result7_querydsl.size()); - - formatLog("8.4 HQL"); - var result7_hql = manager.createQuery( - """ - from Employee employee - where employee.active is true - and employee.age > 25 - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN - and employee.name != 'Alice Smith' - or employee.name = 'Charlie' - """, - Employee.class - ).getResultList(); - Assert.isTrue(result7_hql.size() == 2, "HQL 链式调用失败 (%d)".formatted(result7_hql.size())); - log.info("HQL 结果: {} 条记录", result7_hql.size()); - - // ==================== 测试阶段 9: Join 操作查询 ==================== - formatLog("阶段 9: Join 操作查询"); - log.info("查询条件: company.name='TechCorp' AND company.name!='DataInc' AND skill.name='Java' AND skill.name!='MySQL' AND prop.value='Senior' AND prop.value!='Junior'"); - - formatLog("9.1 JPA Specification"); - // 查找公司名为TechCorp、技能包含Java、属性值为Senior的员工(使用join、fetch、集合join、map join) - var result8_jpa = employeeRepository.findAll((root, query, cb) -> { - return cb.and( - // Company Join 条件 - cb.equal(root.join(Employee_.company).get(Company_.name), "TechCorp"), - cb.notEqual(root.join(Employee_.company).get(Company_.name), "DataInc"), - // Skills Join 条件 - cb.equal(root.join(Employee_.skills).get(Skill_.name), "Java"), - cb.notEqual(root.join(Employee_.skills).get(Skill_.name), "MySQL"), - // Map Join 条件 - cb.equal(root.join(Employee_.properties).value(), "Senior"), - cb.notEqual(root.join(Employee_.properties).value(), "Junior") - ); - }); - Assert.isTrue(result8_jpa.size() == 1, "JPA Specification Join 查询失败 (%d)".formatted(result8_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result8_jpa.size()); - - formatLog("9.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持显式的join操作: - - root.join() - 显式关联查询 - - root.fetch() - 显式抓取查询 - - Map join (cb.equal(root.join().value(), ...)) - Fenix主要用于单表条件查询,复杂join操作建议使用JPA Specification原生方式或QueryDSL - 可以通过doAny使用原生CriteriaBuilder实现join操作 - 注意:由于类型系统的限制,doAny中使用join可能会有类型推断问题 - 建议:对于join等复杂查询,直接使用JPA Specification原生方式"""); - - formatLog("9.3 QueryDSL"); - var result8_querydsl = employeeRepository.findAll( - QEmployee.employee.company().name.eq("TechCorp") - .and(QEmployee.employee.company().name.ne("DataInc")) - .and(QEmployee.employee.skills.any().name.eq("Java")) - .and(QEmployee.employee.skills.any().name.ne("MySQL")) - .and(QEmployee.employee.properties.containsValue("Senior")) - .and(QEmployee.employee.properties.containsValue("Junior").not()) - ); - Assert.isTrue(result8_querydsl.size() == 1, "QueryDSL Join 查询失败 (%d)".formatted(result8_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result8_querydsl.size()); - - formatLog("9.4 HQL"); - var result8_hql = manager.createQuery( - """ - from Employee employee - join employee.company as company - join employee.skills as skill - join employee.properties as prop - where company.name = 'TechCorp' - and company.name != 'DataInc' - and skill.name = 'Java' - and skill.name != 'MySQL' - and value(prop) = 'Senior' - and value(prop) != 'Junior' - """, - Employee.class - ).getResultList(); - Assert.isTrue(result8_hql.size() == 1, "HQL Join 查询失败 (%d)".formatted(result8_hql.size())); - log.info("HQL 结果: {} 条记录", result8_hql.size()); - - // ==================== 测试阶段 10: 子查询和聚合函数查询 ==================== - formatLog("阶段 10: 子查询和聚合函数查询"); - log.info("查询条件: salary>AVG(salary) AND 5<>COUNT(id) AND salary+COALESCE(bonus,0)>55000 AND salary+COALESCE(bonus,0)<70000 AND active=true AND name!='David' AND age>28 AND role!=USER"); - - formatLog("10.1 JPA Specification"); - // 查找薪资高于平均薪资、总记录数不为5、总薪酬在55000-70000之间、激活状态为true、姓名不为David、年龄大于28、角色不是USER的员工 - var result9_jpa = employeeRepository.findAll((root, query, cb) -> { - var avgSalarySubquery = query.subquery(Double.class); - var avgSubRoot = avgSalarySubquery.from(Employee.class); - avgSalarySubquery.select(cb.avg(avgSubRoot.get(Employee_.salary))); - - var countSubquery = query.subquery(Long.class); - var countSubRoot = countSubquery.from(Employee.class); - countSubquery.select(cb.count(countSubRoot)); - - var salary = root.get(Employee_.salary).as(BigDecimal.class); - var bonus = root.get(Employee_.bonus).as(BigDecimal.class); - var totalCompensation = cb.sum(salary, cb.coalesce(bonus, cb.literal(new BigDecimal("0.00")))); - - return cb.and( - cb.greaterThan(root.get(Employee_.salary).as(Double.class), avgSalarySubquery), - cb.notEqual(cb.literal(5L), countSubquery), - cb.greaterThan(totalCompensation, cb.literal(new BigDecimal("55000.00"))), - cb.lessThan(totalCompensation, cb.literal(new BigDecimal("70000.00"))), - cb.isTrue(root.get(Employee_.active)), - cb.notEqual(root.get(Employee_.name), "David"), - cb.greaterThan(root.get(Employee_.age), 28), - cb.notEqual(root.get(Employee_.role), Employee.Role.USER) - ); - }); - Assert.isTrue(result9_jpa.isEmpty(), "JPA Specification 子查询(聚合函数)+ 数学运算失败 (%d)".formatted(result9_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result9_jpa.size()); - - formatLog("10.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持以下高级查询特性: - - query.subquery() - 子查询 - - cb.avg(), cb.count(), cb.sum() - 聚合函数 - - cb.coalesce() - 空值替换函数 - - cb.sum() - 数值加法运算 - 这些是SQL级别的复杂查询,Fenix主要用于动态条件构建 - 可以通过doAny使用原生CriteriaBuilder实现部分聚合操作"""); - - formatLog("10.3 QueryDSL"); - var avgQuery = factory.select(QEmployee.employee.salary.avg()); - var countQuery = factory.select(QEmployee.employee.count()); - var result9_querydsl = employeeRepository.findAll( - QEmployee.employee.salary.gt(avgQuery) - .and(countQuery.ne(5L)) - .and(QEmployee.employee.salary.add(QEmployee.employee.bonus.coalesce(new BigDecimal("0.00"))).gt(new BigDecimal("55000.00"))) - .and(QEmployee.employee.salary.add(QEmployee.employee.bonus.coalesce(new BigDecimal("0.00"))).lt(new BigDecimal("70000.00"))) - .and(QEmployee.employee.active.isTrue()) - .and(QEmployee.employee.name.ne("David")) - .and(QEmployee.employee.age.gt(28)) - .and(QEmployee.employee.role.ne(Employee.Role.USER)) - ); - Assert.isTrue(result9_querydsl.isEmpty(), "QueryDSL 子查询(聚合函数)+ 数学运算失败 (%d)".formatted(result9_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result9_querydsl.size()); - - formatLog("10.4 HQL"); - var result9_hql = manager.createQuery( - """ - from Employee employee - where employee.salary > (select avg(e.salary) from Employee e) - and 5 <> (select count(e.id) from Employee e) - and employee.salary + coalesce(employee.bonus, 0.00) > 55000.00 - and employee.salary + coalesce(employee.bonus, 0.00) < 70000.00 - and employee.active is true - and employee.name != 'David' - and employee.age > 28 - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.USER - """, - Employee.class - ).getResultList(); - Assert.isTrue(result9_hql.isEmpty(), "HQL 子查询(聚合函数)+ 数学运算失败 (%d)".formatted(result9_hql.size())); - log.info("HQL 结果: {} 条记录", result9_hql.size()); - - // ==================== 测试阶段 11: 排序查询 ==================== - formatLog("阶段 11: 排序查询"); - log.info("查询条件: active=true AND role!=ADMIN AND age>20 AND salary<60000 ORDER BY age DESC, name ASC"); - - formatLog("11.1 JPA Specification"); - // 查找激活状态为true、角色不是ADMIN、年龄大于20、薪资小于60000的员工,按年龄降序、姓名升序排序 - var result10_jpa = employeeRepository.findAll( - (root, query, cb) -> cb.and( - cb.isTrue(root.get(Employee_.active)), - cb.notEqual(root.get(Employee_.role), Employee.Role.ADMIN), - cb.greaterThan(root.get(Employee_.age), 20), - cb.lessThan(root.get(Employee_.salary), new BigDecimal("60000.00")) - ), - Sort.by( - Sort.Order.desc(Employee_.AGE), - Sort.Order.asc(Employee_.NAME) - ) - ); - Assert.isTrue(result10_jpa.size() == 3, "JPA Specification 排序查询失败 (%d)".formatted(result10_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result10_jpa.size()); - - formatLog("11.2 Fenix"); - log.info(""" - Fenix框架使用Spring Data JPA原生的Sort对象进行排序 - Fenix构建查询条件,Sort对象通过repository.findAll()的第二个参数传入"""); - var result10_fenix = employeeRepository.findAll( - builder -> builder.andEquals(Employee.Fields.active, true) - .andNotEquals(Employee.Fields.role, Employee.Role.ADMIN) - .andGreaterThan(Employee.Fields.age, 20) - .andLessThan(Employee.Fields.salary, new BigDecimal("60000.00")) - .build(), - Sort.by( - Sort.Order.desc(Employee.Fields.age), - Sort.Order.asc(Employee.Fields.name) - ) - ); - Assert.isTrue(result10_fenix.size() == 3, "Fenix 排序查询失败 (%d)".formatted(result10_fenix.size())); - log.info("Fenix 结果: {} 条记录", result10_fenix.size()); - - formatLog("11.3 QueryDSL"); - var result10_querydsl = employeeRepository.findAll( - QEmployee.employee.active.isTrue() - .and(QEmployee.employee.role.ne(Employee.Role.ADMIN)) - .and(QEmployee.employee.age.gt(20)) - .and(QEmployee.employee.salary.lt(new BigDecimal("60000.00"))), - QEmployee.employee.age.desc(), - QEmployee.employee.name.asc() - ); - Assert.isTrue(result10_querydsl.size() == 3, "QueryDSL 排序查询失败 (%d)".formatted(result10_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result10_querydsl.size()); - - formatLog("11.4 HQL"); - var result10_hql = manager.createQuery( - """ - from Employee employee - where employee.active is true - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN - and employee.age > 20 - and employee.salary < 60000.00 - order by employee.age desc, employee.name asc - """, - Employee.class - ).getResultList(); - Assert.isTrue(result10_hql.size() == 3, "HQL 排序查询失败 (%d)".formatted(result10_hql.size())); - log.info("HQL 结果: {} 条记录", result10_hql.size()); - - // ==================== 测试阶段 12: 分页查询 ==================== - formatLog("阶段 12: 分页查询"); - log.info("查询条件: active=true AND role!=ADMIN AND age>20 AND salary<60000 ORDER BY age LIMIT 2 OFFSET 0"); - - formatLog("12.1 JPA Specification"); - // 分页查找激活状态为true、角色不是ADMIN、年龄大于20、薪资小于60000的员工,每页2条,按年龄排序 - var page11_jpa = employeeRepository.findAll( - (root, query, cb) -> cb.and( - cb.isTrue(root.get(Employee_.active)), - cb.notEqual(root.get(Employee_.role), Employee.Role.ADMIN), - cb.greaterThan(root.get(Employee_.age), 20), - cb.lessThan(root.get(Employee_.salary), new BigDecimal("60000.00")) - ), - PageRequest.of(0, 2, Sort.by(Employee_.AGE)) - ); - Assert.isTrue(page11_jpa.getContent().size() == 2, "JPA Specification 分页大小不正确 (%d)".formatted(page11_jpa.getContent().size())); - Assert.isTrue(page11_jpa.getTotalElements() == 3, "JPA Specification 总元素数不正确 (%d)".formatted(page11_jpa.getTotalElements())); - log.info("JPA Specification 结果: {} 条记录,总记录数: {}", page11_jpa.getContent().size(), page11_jpa.getTotalElements()); - - formatLog("12.2 Fenix"); - log.info(""" - Fenix框架使用Spring Data JPA原生的Pageable对象进行分页 - Fenix构建查询条件,Pageable对象通过repository.findAll()的第二个参数传入"""); - var page11_fenix = employeeRepository.findAll( - builder -> builder.andEquals(Employee.Fields.active, true) - .andNotEquals(Employee.Fields.role, Employee.Role.ADMIN) - .andGreaterThan(Employee.Fields.age, 20) - .andLessThan(Employee.Fields.salary, new BigDecimal("60000.00")) - .build(), - PageRequest.of(0, 2, Sort.by(Employee.Fields.age)) - ); - Assert.isTrue(page11_fenix.getContent().size() == 2, "Fenix 分页大小不正确 (%d)".formatted(page11_fenix.getContent().size())); - Assert.isTrue(page11_fenix.getTotalElements() == 3, "Fenix 总元素数不正确 (%d)".formatted(page11_fenix.getTotalElements())); - log.info("Fenix 结果: {} 条记录,总记录数: {}", page11_fenix.getContent().size(), page11_fenix.getTotalElements()); - - formatLog("12.3 QueryDSL"); - log.info(""" - QueryDSL支持分页查询: - - offset() - 跳过记录数 - - limit() - 限制记录数 - - 也可以结合Spring Data JPA的Pageable对象"""); - var page11_querydsl = employeeRepository.findAll( - QEmployee.employee.active.isTrue() - .and(QEmployee.employee.role.ne(Employee.Role.ADMIN)) - .and(QEmployee.employee.age.gt(20)) - .and(QEmployee.employee.salary.lt(new BigDecimal("60000.00"))), - PageRequest.of(0, 2, Sort.by(QEmployee.employee.age.getMetadata().getName())) - ); - Assert.isTrue(page11_querydsl.getContent().size() == 2, "QueryDSL 分页大小不正确 (%d)".formatted(page11_querydsl.getContent().size())); - Assert.isTrue(page11_querydsl.getTotalElements() == 3, "QueryDSL 总元素数不正确 (%d)".formatted(page11_querydsl.getTotalElements())); - log.info("QueryDSL 结果: {} 条记录,总记录数: {}", page11_querydsl.getContent().size(), page11_querydsl.getTotalElements()); - - formatLog("12.4 HQL"); - var page11_hql = manager.createQuery( - """ - from Employee employee - where employee.active is true - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN - and employee.age > 20 - and employee.salary < 60000.00 - order by employee.age - """, - Employee.class - ).setFirstResult(0).setMaxResults(2).getResultList(); - var total11_hql = manager.createQuery( - """ - from Employee employee - where employee.active is true - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.ADMIN - and employee.age > 20 - and employee.salary < 60000.00 - """, - Employee.class - ).getResultList().size(); - Assert.isTrue(page11_hql.size() == 2, "HQL 分页大小不正确 (%d)".formatted(page11_hql.size())); - Assert.isTrue(total11_hql == 3, "HQL 总元素数不正确 (%d)".formatted(total11_hql)); - log.info("HQL 结果: {} 条记录,总记录数: {}", page11_hql.size(), total11_hql); - - // ==================== 测试阶段 13: CASE WHEN 条件表达式查询 ==================== - formatLog("阶段 13: CASE WHEN 条件表达式查询"); - log.info("查询条件: CASE WHEN age>30 THEN 'Senior' WHEN age BETWEEN 25-30 THEN 'Middle' ELSE 'Junior' END = 'Senior' AND CASE WHEN age>30 THEN 'Senior' WHEN age BETWEEN 25-30 THEN 'Middle' ELSE 'Junior' END != 'Junior'"); - - formatLog("13.1 JPA Specification"); - // 查找年龄大于30(Senior)或年龄在25-30之间(Middle)的员工,排除Junior级别的员工 - var result12_jpa = employeeRepository.findAll((root, query, cb) -> cb.and( - cb.equal( - cb.selectCase() - .when(cb.greaterThan(root.get(Employee_.age), 30), "Senior") - .when(cb.between(root.get(Employee_.age), 25, 30), "Middle") - .otherwise("Junior"), - "Senior" - ), - cb.notEqual( - cb.selectCase() - .when(cb.greaterThan(root.get(Employee_.age), 30), "Senior") - .when(cb.between(root.get(Employee_.age), 25, 30), "Middle") - .otherwise("Junior"), - "Junior" - ) - )); - Assert.isTrue(result12_jpa.size() == 2, "JPA Specification CASE WHEN 查询失败 (%d)".formatted(result12_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result12_jpa.size()); - - formatLog("13.2 Fenix"); - log.info(""" - Fenix框架当前版本不支持CASE WHEN条件表达式: - - cb.selectCase() - SQL CASE WHEN表达式 - - .when() - CASE WHEN条件分支 - - .otherwise() - CASE ELSE分支 - CASE WHEN是SQL级别的条件表达式,Fenix主要用于动态条件构建 - 可以通过doAny使用原生CriteriaBuilder实现CASE WHEN操作 - 注意:由于类型系统的限制,doAny中使用CriteriaBuilder的复杂表达式可能会有类型推断问题 - 建议:对于CASE WHEN等复杂查询,直接使用JPA Specification原生方式"""); - var result12_fenix = employeeRepository.findAll(builder -> { - return builder.doAny(null, null, (cb, root, fieldName, value) -> { - // 使用原生JPA Criteria实现CASE WHEN(简化版本) - var caseExpr = cb.selectCase() - .when(cb.greaterThan(root.get("age"), 30), "Senior") - .when(cb.between(root.get("age"), 25, 30), "Middle") - .otherwise("Junior"); - return cb.and( - cb.equal(caseExpr, "Senior"), - cb.notEqual(caseExpr, "Junior") - ); - }).build(); - }); - Assert.isTrue(result12_fenix.size() == 2, "Fenix CASE WHEN 查询失败 (%d)".formatted(result12_fenix.size())); - log.info("Fenix 结果: {} 条记录", result12_fenix.size()); - - formatLog("13.3 QueryDSL"); - var caseExpr = new CaseBuilder() - .when(QEmployee.employee.age.gt(30)).then("Senior") - .when(QEmployee.employee.age.between(25, 30)).then("Middle") - .otherwise("Junior"); - var result12_querydsl = employeeRepository.findAll( - caseExpr.eq("Senior").and(caseExpr.ne("Junior")) - ); - Assert.isTrue(result12_querydsl.size() == 2, "QueryDSL CASE WHEN 查询失败 (%d)".formatted(result12_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result12_querydsl.size()); - - formatLog("13.4 HQL"); - var result12_hql = manager.createQuery( - """ - from Employee employee - where (case when employee.age > 30 then 'Senior' - when employee.age between 25 and 30 then 'Middle' - else 'Junior' - end) = 'Senior' - and (case when employee.age > 30 then 'Senior' - when employee.age between 25 and 30 then 'Middle' - else 'Junior' - end) != 'Junior' - """, - Employee.class - ).getResultList(); - Assert.isTrue(result12_hql.size() == 2, "HQL CASE WHEN 查询失败 (%d)".formatted(result12_hql.size())); - log.info("HQL 结果: {} 条记录", result12_hql.size()); - - // ==================== 测试阶段 14: 综合多条件查询 ==================== - formatLog("阶段 14: 综合多条件查询"); - log.info("查询条件: company.name='TechCorp' AND company.name!='DataInc' AND skill.name='Java' AND skill.name!='MySQL' AND address.city='Beijing' AND address.city!='Shanghai' AND skills IS NOT EMPTY AND hobbies IS NOT EMPTY AND properties IS NOT EMPTY AND createdTime IS NOT NULL AND modifiedTime IS NOT NULL AND active=true AND name!='Alice Smith' AND age>25 AND role!=USER"); - - formatLog("14.1 JPA Specification"); - // 综合查询:公司名为TechCorp、技能包含Java、城市为Beijing、技能和爱好非空、属性非空、创建和修改时间不为null、激活状态为true、姓名不为Alice Smith、年龄大于25、角色不是USER - var result13_jpa = employeeRepository.findAll((root, query, cb) -> { - query.distinct(true); - return cb.and( - // Company Join 条件 - cb.equal(root.join(Employee_.company).get(Company_.name), "TechCorp"), - cb.notEqual(root.join(Employee_.company).get(Company_.name), "DataInc"), - // Skills Join 条件 - cb.equal(root.join(Employee_.skills).get(Skill_.name), "Java"), - cb.notEqual(root.join(Employee_.skills).get(Skill_.name), "MySQL"), - // Embedded 对象条件 - cb.equal(root.get(Employee_.address).get(Address_.city), "Beijing"), - cb.notEqual(root.get(Employee_.address).get(Address_.city), "Shanghai"), - // 集合条件 - cb.isNotEmpty(root.get(Employee_.skills)), - cb.not(cb.isEmpty(root.get(Employee_.hobbies))), - // Map 条件 - cb.isNotEmpty(root.get(Employee_.properties)), - // 日期时间字段查询 - cb.isNotNull(root.get(Employee_.createdTime)), - cb.isNotNull(root.get(Employee_.modifiedTime)), - // 其他条件 - cb.isTrue(root.get(Employee_.active)), - cb.notEqual(root.get(Employee_.name), "Alice Smith"), - cb.greaterThan(root.get(Employee_.age), 25), - cb.notEqual(root.get(Employee_.role), Employee.Role.USER) - ); - }); - Assert.isTrue(result13_jpa.size() == 1 && result13_jpa.get(0).getName().equals("Alice"), "JPA Specification 综合多条件查询失败 (%d)".formatted(result13_jpa.size())); - log.info("JPA Specification 结果: {} 条记录", result13_jpa.size()); - - formatLog("14.2 Fenix"); - log.info(""" - Fenix框架不支持综合多条件查询中的复杂join和集合操作: - - 显式join操作(company, skills, properties) - - 集合isEmpty/isNotEmpty/isMember操作 - - Map join操作 - - 嵌入式对象查询(address.city) - Fenix主要支持简单的单表字段查询 - 可以通过doAny使用原生CriteriaBuilder实现复杂综合查询"""); - - formatLog("14.3 QueryDSL"); - var result13_querydsl = employeeRepository.findAll( - // Company Join 条件 - QEmployee.employee.company().name.eq("TechCorp") - .and(QEmployee.employee.company().name.ne("DataInc")) - // Skills Join 条件 - .and(QEmployee.employee.skills.any().name.eq("Java")) - .and(QEmployee.employee.skills.any().name.ne("MySQL")) - // Embedded 对象条件 - .and(QEmployee.employee.address().city.eq("Beijing")) - .and(QEmployee.employee.address().city.ne("Shanghai")) - // 集合条件 - .and(QEmployee.employee.skills.isNotEmpty()) - .and(QEmployee.employee.hobbies.isNotEmpty()) - // Map 条件 - // .and(QEmployee.employee.properties.isNotEmpty()) - // 日期时间字段查询 - .and(QEmployee.employee.createdTime.isNotNull()) - .and(QEmployee.employee.modifiedTime.isNotNull()) - // 其他条件 - .and(QEmployee.employee.active.isTrue()) - .and(QEmployee.employee.name.ne("Alice Smith")) - .and(QEmployee.employee.age.gt(25)) - .and(QEmployee.employee.role.ne(Employee.Role.USER)) - ); - Assert.isTrue(result13_querydsl.size() == 1 && result13_querydsl.get(0).getName().equals("Alice"), "QueryDSL 综合多条件查询失败 (%d)".formatted(result13_querydsl.size())); - log.info("QueryDSL 结果: {} 条记录", result13_querydsl.size()); - - formatLog("14.4 HQL"); - var result13_hql = manager.createQuery( - """ - select distinct employee - from Employee employee - join employee.company as company - join employee.skills as skill - where company.name = 'TechCorp' - and company.name != 'DataInc' - and skill.name = 'Java' - and skill.name != 'MySQL' - and employee.address.city = 'Beijing' - and employee.address.city != 'Shanghai' - and employee.skills is not empty - and employee.hobbies is not empty - and employee.properties is not empty - and employee.createdTime is not null - and employee.modifiedTime is not null - and employee.active is true - and employee.name != 'Alice Smith' - and employee.age > 25 - and employee.role != com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee.Role.USER - """, - Employee.class - ).getResultList(); - Assert.isTrue(result13_hql.size() == 1 && result13_hql.get(0).getName().equals("Alice"), "HQL 综合多条件查询失败 (%d)".formatted(result13_hql.size())); - log.info("HQL 结果: {} 条记录", result13_hql.size()); - - // ==================== 测试阶段 15: 清理测试数据 ==================== - formatLog("阶段 15: 清理测试数据"); - employeeRepository.deleteAllInBatch(); - companyRepository.deleteAllInBatch(); - log.info("测试数据清理完成"); - } - - private void testMethodQuery() { - formatLog("准备 Query Method 测试数据"); - var company1 = companyRepository.save(Company.builder().name("TechCorp").members(100).build()); - var company2 = companyRepository.save(Company.builder().name("DataInc").members(50).build()); - var company3 = companyRepository.save(Company.builder().name("CloudSys").members(150).build()); - - var skill1 = Skill.builder().name("Java").description("Java 编程语言").build(); - var skill2 = Skill.builder().name("Python").description("Python 编程语言").build(); - var skill3 = Skill.builder().name("Spring").description("Spring 框架").build(); - var skill4 = Skill.builder().name("MySQL").description("MySQL 数据库").build(); - - var emp1 = employeeRepository.save(Employee.builder() - .name("Alice").age(30).role(Employee.Role.ADMIN).code("E001") - .salary(new BigDecimal("50000.00")).bonus(new BigDecimal("5000.00")) - .active(true).company(company1) - .address(Address.builder().street("Main St").city("Beijing").state("Beijing").zipCode("100000").country("China").build()) - .skills(Set.of(skill1, skill3)) - .hobbies(List.of("Reading", "Swimming")) - .properties(Map.of("department", "Engineering", "level", "Senior")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "alice@example.com")) - .build()); - - var emp2 = employeeRepository.save(Employee.builder() - .name("Bob").age(25).role(Employee.Role.USER).code("E002") - .salary(new BigDecimal("40000.00")).bonus(new BigDecimal("4000.00")) - .active(true).company(company2) - .address(Address.builder().street("Oak Ave").city("Shanghai").state("Shanghai").zipCode("200000").country("China").build()) - .skills(Set.of(skill2)) - .hobbies(List.of("Gaming")) - .properties(Map.of("department", "Marketing", "level", "Junior")) - .connections(Map.of(Employee.ConnectionType.PHONE, "1234567890")) - .build()); - - var emp3 = employeeRepository.save(Employee.builder() - .name("Charlie").age(35).role(Employee.Role.ADMIN).code("E003") - .salary(new BigDecimal("60000.00")).bonus(new BigDecimal("6000.00")) - .active(false).company(company1) - .address(Address.builder().street("Pine Rd").city("Shenzhen").state("Guangdong").zipCode("518000").country("China").build()) - .skills(Set.of(skill1, skill2, skill3)) - .hobbies(List.of("Reading", "Gaming", "Music")) - .properties(Map.of("department", "Engineering", "level", "Lead")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "charlie@example.com", Employee.ConnectionType.PHONE, "0987654321")) - .build()); - - var emp4 = employeeRepository.save(Employee.builder() - .name("David").age(28).role(Employee.Role.USER).code("E004") - .salary(new BigDecimal("45000.00")).bonus(null) - .active(true).company(company3) - .address(Address.builder().street("Elm Ln").city("Guangzhou").state("Guangdong").zipCode("510000").country("China").build()) - .skills(Set.of(skill4)) - .hobbies(List.of()) - .properties(Map.of()) - .connections(Map.of()) - .build()); - - var emp5 = employeeRepository.save(Employee.builder() - .name("Alice Smith").age(32).role(Employee.Role.USER).code("E005") - .salary(new BigDecimal("55000.00")).bonus(new BigDecimal("5500.00")) - .active(true).company(company2) - .address(Address.builder().street("Maple Dr").city("Hangzhou").state("Zhejiang").zipCode("310000").country("China").build()) - .skills(Set.of(skill1, skill4)) - .hobbies(List.of("Swimming", "Music")) - .properties(Map.of("department", "Sales", "level", "Middle")) - .connections(Map.of(Employee.ConnectionType.EMAIL, "alicesmith@example.com")) - .build()); - - // ==================== 1. 基本字段查询测试 ==================== - - formatLog("1.1 单字段精确匹配查询"); - var r1_1 = employeeRepository.findByName("Bob"); - Assert.isTrue(!r1_1.isEmpty(), "findByName failed"); - Assert.isTrue(r1_1.get(0).getName().equals("Bob"), "findByName 结果不正确"); - - var r1_2 = employeeRepository.findByCode("E003"); - Assert.isTrue(r1_2.isPresent(), "findByCode failed"); - Assert.isTrue(r1_2.orElseThrow().getCode().equals("E003"), "findByCode 结果不正确"); - - var r1_3 = employeeRepository.findByRole(Employee.Role.ADMIN); - Assert.isTrue(r1_3.size() == 2, "findByRole 结果数量应为2,实际:" + r1_3.size()); - - formatLog("1.2 布尔值查询"); - var r1_4 = employeeRepository.findByActiveTrue(); - Assert.isTrue(r1_4.size() == 4, "findByActiveTrue 结果数量应为4,实际:" + r1_4.size()); - - var r1_5 = employeeRepository.findByActiveFalse(); - Assert.isTrue(r1_5.size() == 1, "findByActiveFalse 结果数量应为1,实际:" + r1_5.size()); - - var r1_6 = employeeRepository.countByActiveTrue(); - Assert.isTrue(r1_6 == 4, "countByActiveTrue 结果应为4,实际:" + r1_6); - - // ==================== 2. 比较运算符查询测试 ==================== - - formatLog("2.1 大于/小于/等于/不等于查询"); - var r2_1 = employeeRepository.findByAgeGreaterThan(30); - Assert.isTrue(r2_1.size() == 2, "findByAgeGreaterThan(30) 结果数量应为2,实际:" + r2_1.size()); - - var r2_2 = employeeRepository.findByAgeLessThan(30); - Assert.isTrue(r2_2.size() == 2, "findByAgeLessThan(30) 结果数量应为2,实际:" + r2_2.size()); - - var r2_3 = employeeRepository.findByAgeGreaterThanEqual(30); - Assert.isTrue(r2_3.size() == 3, "findByAgeGreaterThanEqual(30) 结果数量应为3,实际:" + r2_3.size()); - - var r2_4 = employeeRepository.findByAgeLessThanEqual(30); - Assert.isTrue(r2_4.size() == 3, "findByAgeLessThanEqual(30) 结果数量应为3,实际:" + r2_4.size()); - - var r2_5 = employeeRepository.findByAgeBetween(25, 35); - Assert.isTrue(r2_5.size() == 4, "findByAgeBetween(25,35) 结果数量应为4,实际:" + r2_5.size()); - - formatLog("2.2 薪资范围查询"); - var r2_6 = employeeRepository.findBySalaryGreaterThan(new BigDecimal("50000.00")); - Assert.isTrue(r2_6.size() == 3, "findBySalaryGreaterThan 结果数量应为3,实际:" + r2_6.size()); - - var r2_7 = employeeRepository.findBySalaryLessThan(new BigDecimal("50000.00")); - Assert.isTrue(r2_7.size() == 2, "findBySalaryLessThan 结果数量应为2,实际:" + r2_7.size()); - - var r2_8 = employeeRepository.findBySalaryBetween(new BigDecimal("40000.00"), new BigDecimal("55000.00")); - Assert.isTrue(r2_8.size() == 4, "findBySalaryBetween 结果数量应为4,实际:" + r2_8.size()); - - // ==================== 3. 字符串匹配查询测试 ==================== - - formatLog("3.1 字符串包含/开头/结尾查询"); - var r3_1 = employeeRepository.findByNameContaining("Alice"); - Assert.isTrue(r3_1.size() == 2, "findByNameContaining('Alice') 结果数量应为2,实际:" + r3_1.size()); - - var r3_2 = employeeRepository.findByNameStartingWith("A"); - Assert.isTrue(r3_2.size() == 2, "findByNameStartingWith('A') 结果数量应为2,实际:" + r3_2.size()); - - var r3_3 = employeeRepository.findByNameEndingWith("e"); - Assert.isTrue(r3_3.size() == 3, "findByNameEndingWith('e') 结果数量应为3,实际:" + r3_3.size()); - - var r3_4 = employeeRepository.findByNameLike("%ar%"); - Assert.isTrue(r3_4.size() == 1, "findByNameLike('%ar%') 结果数量应为1,实际:" + r3_4.size()); - - formatLog("3.2 忽略大小写查询"); - var r3_5 = employeeRepository.findByNameContainingIgnoreCase("ALICE"); - Assert.isTrue(r3_5.size() == 2, "findByNameContainingIgnoreCase('ALICE') 结果数量应为2,实际:" + r3_5.size()); - - var r3_6 = employeeRepository.findByNameStartingWithIgnoreCase("B"); - Assert.isTrue(r3_6.size() == 1, "findByNameStartingWithIgnoreCase('B') 结果数量应为1,实际:" + r3_6.size()); - - var r3_7 = employeeRepository.findByNameIgnoreCase("BOB"); - Assert.notNull(r3_7, "findByNameIgnoreCase('BOB') 返回null"); - - // ==================== 4. NULL值和空值查询测试 ==================== - - formatLog("4.1 NULL值查询"); - var r4_1 = employeeRepository.findByBonusIsNull(); - Assert.isTrue(r4_1.size() == 1, "findByBonusIsNull 结果数量应为1,实际:" + r4_1.size()); - Assert.isTrue(r4_1.get(0).getName().equals("David"), "findByBonusIsNull 结果应为David"); - - var r4_2 = employeeRepository.findByBonusIsNotNull(); - Assert.isTrue(r4_2.size() == 4, "findByBonusIsNotNull 结果数量应为4,实际:" + r4_2.size()); - - var r4_3 = employeeRepository.findByResumeIsNull(); - Assert.isTrue(r4_3.size() == 5, "findByResumeIsNull 结果数量应为5,实际:" + r4_3.size()); - - formatLog("4.2 空集合查询"); - var r4_4 = employeeRepository.findByHobbiesEmpty(); - Assert.isTrue(r4_4.size() == 1, "findByHobbiesEmpty 结果数量应为1,实际:" + r4_4.size()); - - var r4_5 = employeeRepository.findByHobbiesIsNotEmpty(); - Assert.isTrue(r4_5.size() == 4, "findByHobbiesIsNotEmpty 结果数量应为4,实际:" + r4_5.size()); - - // ==================== 5. 集合成员查询测试 ==================== - - formatLog("5.1 IN/NOT IN 查询"); - var r5_1 = employeeRepository.findByRoleIn(Set.of(Employee.Role.ADMIN)); - Assert.isTrue(r5_1.size() == 2, "findByRoleIn 结果数量应为2,实际:" + r5_1.size()); - - var r5_2 = employeeRepository.findByRoleNotIn(Set.of(Employee.Role.ADMIN)); - Assert.isTrue(r5_2.size() == 3, "findByRoleNotIn 结果数量应为3,实际:" + r5_2.size()); - - var r5_3 = employeeRepository.findByNameIn(List.of("Alice", "Bob")); - Assert.isTrue(r5_3.size() == 2, "findByNameIn 结果数量应为2,实际:" + r5_3.size()); - - var r5_4 = employeeRepository.findByNameNotIn(List.of("Charlie", "David")); - Assert.isTrue(r5_4.size() == 3, "findByNameNotIn 结果数量应为3,实际:" + r5_4.size()); - - var r5_5 = employeeRepository.findByAgeIn(List.of(25, 30, 35)); - Assert.isTrue(r5_5.size() == 3, "findByAgeIn 结果数量应为3,实际:" + r5_5.size()); - - // ==================== 6. 逻辑运算查询测试 ==================== - - formatLog("6.1 AND 组合查询"); - var r6_1 = employeeRepository.findByNameAndRole("Alice", Employee.Role.ADMIN); - Assert.isTrue(r6_1.size() == 1, "findByNameAndRole 结果数量应为1,实际:" + r6_1.size()); - - var r6_2 = employeeRepository.findByAgeAndActive(30, true); - Assert.isTrue(r6_2.size() == 1, "findByAgeAndActive 结果数量应为1,实际:" + r6_2.size()); - - var r6_3 = employeeRepository.findByNameAndSalaryGreaterThan("Alice", new BigDecimal("40000.00")); - Assert.isTrue(r6_3.size() == 1, "findByNameAndSalaryGreaterThan 结果数量应为1,实际:" + r6_3.size()); - - formatLog("6.2 OR 组合查询"); - var r6_4 = employeeRepository.findByNameOrRole("Alice", Employee.Role.USER); - Assert.isTrue(r6_4.size() == 4, "findByNameOrRole 结果数量应为4,实际:" + r6_4.size()); - - var r6_5 = employeeRepository.findByAgeLessThanOrSalaryGreaterThan(30, new BigDecimal("55000.00")); - Assert.isTrue(r6_5.size() == 3, "findByAgeLessThanOrSalaryGreaterThan 结果数量应为3,实际:" + r6_5.size()); - - var r6_6 = employeeRepository.findByNameOrCode("Alice", "E003"); - Assert.isTrue(r6_6.size() == 2, "findByNameOrCode 结果数量应为2,实际:" + r6_6.size()); - - formatLog("6.3 NOT 查询"); - var r6_7 = employeeRepository.findByRoleNot(Employee.Role.ADMIN); - Assert.isTrue(r6_7.size() == 3, "findByRoleNot 结果数量应为3,实际:" + r6_7.size()); - - var r6_8 = employeeRepository.findByNameNot("Alice"); - Assert.isTrue(r6_8.size() == 4, "findByNameNot 结果数量应为4,实际:" + r6_8.size()); - - // ==================== 7. 排序查询测试 ==================== - - formatLog("7.1 单字段排序查询"); - var r7_1 = employeeRepository.findByActiveTrueOrderByAgeAsc(); - Assert.isTrue(r7_1.size() == 4, "findByActiveTrueOrderByAgeAsc 结果数量应为4"); - Assert.isTrue(r7_1.get(0).getAge() == 25, "findByActiveTrueOrderByAgeAsc 第一条年龄应为25"); - - var r7_2 = employeeRepository.findByActiveTrueOrderByAgeDesc(); - Assert.isTrue(r7_2.size() == 4, "findByActiveTrueOrderByAgeDesc 结果数量应为4"); - Assert.isTrue(r7_2.get(0).getAge() == 32, "findByActiveTrueOrderByAgeDesc 第一条年龄应为32"); - - var r7_3 = employeeRepository.findByActiveTrueOrderBySalaryDesc(); - Assert.isTrue(r7_3.size() == 4, "findByActiveTrueOrderBySalaryDesc 结果数量应为4"); - Assert.isTrue(r7_3.get(0).getSalary().compareTo(new BigDecimal("55000.00")) == 0, "findByActiveTrueOrderBySalaryDesc 第一条薪资应为55000"); - - formatLog("7.2 多字段排序查询"); - var r7_4 = employeeRepository.findByRoleOrderByAgeDescNameAsc(Employee.Role.ADMIN); - Assert.isTrue(r7_4.size() == 2, "findByRoleOrderByAgeDescNameAsc 结果数量应为2"); - - // ==================== 8. 分页查询测试 ==================== - - formatLog("8.1 分页查询"); - var r8_1 = employeeRepository.findByActiveTrue(PageRequest.of(0, 2)); - Assert.isTrue(r8_1.getContent().size() == 2, "分页结果数量应为2,实际:" + r8_1.getContent().size()); - Assert.isTrue(r8_1.getTotalElements() == 4, "总元素数应为4,实际:" + r8_1.getTotalElements()); - - var r8_2 = employeeRepository.findByRole(Employee.Role.USER, PageRequest.of(0, 10)); - Assert.isTrue(r8_2.getContent().size() == 3, "findByRole 分页结果数量应为3,实际:" + r8_2.getContent().size()); - - var r8_3 = employeeRepository.findBySalaryGreaterThan(new BigDecimal("45000.00"), PageRequest.of(0, 2)); - Assert.isTrue(r8_3.getContent().size() == 2, "findBySalaryGreaterThan 分页结果数量应为2"); - - // ==================== 9. 关联查询测试 ==================== - - formatLog("9.1 公司关联查询"); - var r9_1 = employeeRepository.findByCompany(company1); - Assert.isTrue(r9_1.size() == 2, "findByCompany 结果数量应为2,实际:" + r9_1.size()); - - var r9_2 = employeeRepository.findByCompanyName("TechCorp"); - Assert.isTrue(r9_2.size() == 2, "findByCompanyName 结果数量应为2,实际:" + r9_2.size()); - - var r9_3 = employeeRepository.findByCompanyNameContaining("Corp"); - Assert.isTrue(r9_3.size() == 2, "findByCompanyNameContaining 结果数量应为2,实际:" + r9_3.size()); - - var r9_4 = employeeRepository.findByCompanyMembersGreaterThan(75); - Assert.isTrue(r9_4.size() == 2, "findByCompanyMembersGreaterThan 结果数量应为2,实际:" + r9_4.size()); - - formatLog("9.2 技能关联查询"); - var r9_5 = employeeRepository.findBySkillsContaining(skill1); - Assert.isTrue(r9_5.size() == 3, "findBySkillsContaining 结果数量应为3,实际:" + r9_5.size()); - - var r9_6 = employeeRepository.findBySkillsName("Java"); - Assert.isTrue(r9_6.size() == 3, "findBySkillsName 结果数量应为3,实际:" + r9_6.size()); - - var r9_7 = employeeRepository.findBySkillsNameContaining("Pyt"); - Assert.isTrue(r9_7.size() == 2, "findBySkillsNameContaining 结果数量应为2,实际:" + r9_7.size()); - - var r9_8 = employeeRepository.findBySkillsNameIn(List.of("Java", "Python")); - Assert.isTrue(r9_8.size() == 3, "findBySkillsNameIn 结果数量应为3,实际:" + r9_8.size()); - - // ==================== 10. 嵌入式对象查询测试 ==================== - - formatLog("10.1 嵌入式对象查询"); - var r10_1 = employeeRepository.findByAddressCity("Beijing"); - Assert.isTrue(r10_1.size() == 1, "findByAddressCity 结果数量应为1,实际:" + r10_1.size()); - Assert.isTrue(r10_1.get(0).getName().equals("Alice"), "findByAddressCity 结果应为Alice"); - - var r10_2 = employeeRepository.findByAddressCityContaining("ang"); - Assert.isTrue(r10_2.size() == 2, "findByAddressCityContaining 结果数量应为2,实际:" + r10_2.size()); - - var r10_3 = employeeRepository.findByAddressState("Guangdong"); - Assert.isTrue(r10_3.size() == 2, "findByAddressState 结果数量应为2,实际:" + r10_3.size()); - - var r10_4 = employeeRepository.findByAddressCountry("China"); - Assert.isTrue(r10_4.size() == 5, "findByAddressCountry 结果数量应为5,实际:" + r10_4.size()); - - var r10_5 = employeeRepository.findByAddressCityAndAddressState("Shenzhen", "Guangdong"); - Assert.isTrue(r10_5.size() == 1, "findByAddressCityAndAddressState 结果数量应为1"); - - // ==================== 11. 复合复杂查询测试 ==================== - - formatLog("11.1 多条件组合查询"); - var r11_1 = employeeRepository.findByNameAndRoleAndAgeGreaterThan("Alice", Employee.Role.ADMIN, 25); - Assert.isTrue(r11_1.size() == 1, "findByNameAndRoleAndAgeGreaterThan 结果数量应为1"); - - var r11_2 = employeeRepository.findByRoleAndActiveTrueAndSalaryGreaterThan(Employee.Role.USER, new BigDecimal("40000.00")); - Assert.isTrue(r11_2.size() == 2, "findByRoleAndActiveTrueAndSalaryGreaterThan 结果数量应为2"); - - var r11_3 = employeeRepository.findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween("a", 25, 35); - Assert.isTrue(r11_3.size() == 3, "findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween 结果数量应为3"); - - formatLog("11.2 EXISTS语义查询"); - var r11_4 = employeeRepository.findByCompanyNameContainingAndActiveTrue("Corp"); - Assert.isTrue(r11_4.size() == 2, "findByCompanyNameContainingAndActiveTrue 结果数量应为2"); - - var r11_5 = employeeRepository.findBySkillsNameContainingAndAgeGreaterThan("Java", 25); - Assert.isTrue(r11_5.size() == 2, "findBySkillsNameContainingAndAgeGreaterThan 结果数量应为2"); - - // ==================== 12. DISTINCT 查询测试 ==================== - - formatLog("12.1 DISTINCT 查询"); - var r12_1 = employeeRepository.findDistinctByRole(Employee.Role.ADMIN); - Assert.isTrue(r12_1.size() == 2, "findDistinctByRole 结果数量应为2"); - - // ==================== 13. TOP/LIMIT 查询测试 ==================== - - formatLog("13.1 TOP/LIMIT 查询"); - var r13_1 = employeeRepository.findTop5BySalaryGreaterThan(new BigDecimal("40000.00")); - Assert.isTrue(r13_1.size() == 4, "findTop5BySalaryGreaterThan 结果数量应为4"); - - var r13_3 = employeeRepository.findFirstByRoleOrderBySalaryDesc(Employee.Role.ADMIN); - Assert.notNull(r13_3, "findFirstByRoleOrderBySalaryDesc 返回null"); - Assert.isTrue(r13_3.orElseThrow().getSalary().compareTo(new BigDecimal("60000.00")) == 0, "findFirstByRoleOrderBySalaryDesc 最高薪资应为60000"); - - // ==================== 14. LIKE 模式查询测试 ==================== - - formatLog("14.1 LIKE 模式查询"); - var r14_1 = employeeRepository.findByNameLikeIgnoreCase("%ALICE%"); - Assert.isTrue(r14_1.size() == 2, "findByNameLikeIgnoreCase 结果数量应为2"); - - var r14_2 = employeeRepository.findByNameStartingWithAndRole("A", Employee.Role.ADMIN); - Assert.isTrue(r14_2.size() == 1, "findByNameStartingWithAndRole 结果数量应为1"); - - var r14_3 = employeeRepository.findByNameEndingWithAndAgeLessThan("e", 30); - Assert.isTrue(r14_3.size() == 1, "findByNameEndingWithAndAgeLessThan 结果数量应为1"); - - // ==================== 15. 其他未覆盖的有用方法测试 ==================== - - formatLog("15.1 聚合计数查询"); - var r15_1 = employeeRepository.countByActiveTrue(); - Assert.isTrue(r15_1 == 4, "countByActiveTrue 结果应为4,实际:" + r15_1); - - var r15_2 = employeeRepository.countByActiveFalse(); - Assert.isTrue(r15_2 == 1, "countByActiveFalse 结果应为1,实际:" + r15_2); - - formatLog("15.2 技能和简历查询"); - var r15_3 = employeeRepository.findByResumeIsNotNull(); - Assert.isTrue(r15_3.size() == 5, "findByResumeIsNotNull 结果数量应为5,实际:" + r15_3.size()); - - var r15_4 = employeeRepository.findBySkillsEmpty(); - Assert.isTrue(r15_4.isEmpty(), "findBySkillsEmpty 结果应该为空,实际:" + r15_4.size()); - - formatLog("15.3 公司成员数查询"); - var r15_5 = employeeRepository.findByCompanyMembersGreaterThan(100); - Assert.isTrue(r15_5.size() == 1, "findByCompanyMembersGreaterThan(100) 结果数量应为1,实际:" + r15_5.size()); - - var r15_6 = employeeRepository.findByCompanyMembersGreaterThan(50); - Assert.isTrue(r15_6.size() == 3, "findByCompanyMembersGreaterThan(50) 结果数量应为3,实际:" + r15_6.size()); - - formatLog("15.4 城市包含查询"); - var r15_7 = employeeRepository.findByAddressCityContaining("ang"); - Assert.isTrue(r15_7.size() == 2, "findByAddressCityContaining('ang') 结果数量应为2,实际:" + r15_7.size()); - - formatLog("15.5 DISTINCT 查询"); - var r15_8 = employeeRepository.findDistinctByRole(Employee.Role.USER); - Assert.isTrue(r15_8.size() == 3, "findDistinctByRole 结果数量应为3,实际:" + r15_8.size()); - - formatLog("15.6 TOP/LIMIT 查询"); - var r15_9 = employeeRepository.findTop5BySalaryGreaterThan(new BigDecimal("40000.00")); - Assert.isTrue(r15_9.size() == 4, "findTop5BySalaryGreaterThan 结果数量应为4,实际:" + r15_9.size()); - - var r15_10 = employeeRepository.findFirstByRoleOrderBySalaryDesc(Employee.Role.ADMIN); - Assert.isTrue(r15_10.isPresent(), "findFirstByRoleOrderBySalaryDesc 返回null"); - Assert.isTrue(r15_10.orElseThrow().getSalary().compareTo(new BigDecimal("60000.00")) == 0, "findFirstByRoleOrderBySalaryDesc 最高薪资应为60000"); - - formatLog("清理测试数据"); - employeeRepository.deleteAllInBatch(); - companyRepository.deleteAllInBatch(); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/CompanyController.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/CompanyController.java deleted file mode 100644 index 75475e6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/CompanyController.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.controller; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company; -import com.lanyuanxiaoyao.service.template.database.jpa.service.CompanyService; -import java.time.LocalDateTime; -import java.util.function.Function; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("company") -public class CompanyController extends SimpleControllerSupport { - public CompanyController(CompanyService service) { - super(service); - } - - @Override - protected Function saveItemMapper() { - return item -> { - var company = new Company(); - company.setId(item.id()); - company.setName(item.name()); - company.setMembers(item.members()); - return company; - }; - } - - @Override - protected Function listItemMapper() { - return company -> new ListItem( - company.getId(), - company.getName(), - company.getMembers() - ); - } - - @Override - protected Function detailItemMapper() { - return company -> new DetailItem( - company.getId(), - company.getName(), - company.getMembers(), - company.getCreatedTime(), - company.getModifiedTime() - ); - } - - public record SaveItem( - Long id, - String name, - Integer members - ) { - } - - public record ListItem( - Long id, - String name, - Integer members - ) { - } - - public record DetailItem( - Long id, - String name, - Integer members, - LocalDateTime createdTime, - LocalDateTime modifiedTime - ) { - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/EmployeeController.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/EmployeeController.java deleted file mode 100644 index 23c032e..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/EmployeeController.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.controller; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.jpa.service.CompanyService; -import com.lanyuanxiaoyao.service.template.database.jpa.service.EmployeeService; -import java.time.LocalDateTime; -import java.util.function.Function; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("employee") -public class EmployeeController extends SimpleControllerSupport { - private final CompanyService companyService; - - public EmployeeController(EmployeeService service, CompanyService companyService) { - super(service); - this.companyService = companyService; - } - - @Override - protected Function saveItemMapper() { - return item -> { - var employee = new Employee(); - employee.setId(item.id()); - employee.setName(item.name()); - employee.setAge(item.age()); - employee.setRole(Employee.Role.USER); - employee.setCompany(companyService.detailOrThrow(item.companyId())); - return employee; - }; - } - - @Override - protected Function listItemMapper() { - return employee -> new ListItem( - employee.getId(), - employee.getName(), - employee.getAge(), - employee.getRole() - ); - } - - @Override - protected Function detailItemMapper() { - return employee -> new DetailItem( - employee.getId(), - employee.getCompany().getId(), - employee.getName(), - employee.getAge(), - employee.getRole(), - employee.getCreatedTime(), - employee.getModifiedTime() - ); - } - - public record SaveItem( - Long id, - Long companyId, - String name, - Integer age, - Employee.Role role - ) { - } - - public record ListItem( - Long id, - String name, - Integer age, - Employee.Role role - ) { - } - - public record DetailItem( - Long id, - Long companyId, - String name, - Integer age, - Employee.Role role, - LocalDateTime createdTime, - LocalDateTime modifiedTime - ) { - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/ReportController.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/ReportController.java deleted file mode 100644 index 8d67d89..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/ReportController.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.controller; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Report; -import com.lanyuanxiaoyao.service.template.database.jpa.service.EmployeeService; -import com.lanyuanxiaoyao.service.template.database.jpa.service.ReportService; -import java.time.LocalDateTime; -import java.util.function.Function; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("report") -public class ReportController extends SimpleControllerSupport { - private final EmployeeService employeeService; - - public ReportController(ReportService service, EmployeeService employeeService) { - super(service); - this.employeeService = employeeService; - } - - @Override - protected Function saveItemMapper() { - return item -> { - var report = new Report(); - report.setId(item.id()); - report.setScore(item.score()); - report.setLevel(item.level()); - report.setEmployeeId(item.employeeId()); - return report; - }; - } - - @Override - protected Function listItemMapper() { - return report -> { - var employee = employeeService.detailOrThrow(report.getEmployeeId()); - return new ListItem( - report.getId(), - employee.getId(), - employee.getName(), - report.getScore(), - report.getLevel() - ); - }; - } - - @Override - protected Function detailItemMapper() { - return report -> { - var employee = employeeService.detailOrThrow(report.getEmployeeId()); - return new DetailItem( - report.getId(), - employee.getId(), - employee.getName(), - report.getScore(), - report.getLevel(), - report.getCreatedTime(), - report.getModifiedTime() - ); - }; - } - - public record SaveItem( - Long id, - Double score, - Report.Level level, - Long employeeId - ) { - } - - public record ListItem( - Long id, - Long employeeId, - String employeeName, - Double score, - Report.Level level - ) { - } - - public record DetailItem( - Long id, - Long employeeId, - String employeeName, - Double score, - Report.Level level, - LocalDateTime createdTime, - LocalDateTime modifiedTime - ) { - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Address.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Address.java deleted file mode 100644 index aac37e6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Address.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Embeddable -@Setter -@Getter -@ToString -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class Address { - @Column(comment = "街道") - private String street; - - @Column(comment = "城市") - private String city; - - @Column(comment = "省/州") - private String state; - - @Column(comment = "邮政编码") - private String zipCode; - - @Column(comment = "国家") - private String country; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Company.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Company.java deleted file mode 100644 index 6161868..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Company.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.SoftDelete; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -@Setter -@Getter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Entity -@SoftDelete -@DynamicUpdate -@DynamicInsert -@EntityListeners(AuditingEntityListener.class) -@Table(comment = "企业") -public class Company extends SimpleEntity { - @Column(nullable = false, comment = "名称") - private String name; - @Column(nullable = false, comment = "成员数") - private Integer members; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Employee.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Employee.java deleted file mode 100644 index dd82752..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Employee.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.ConstraintMode; -import jakarta.persistence.ElementCollection; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.ForeignKey; -import jakarta.persistence.Index; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.JoinTable; -import jakarta.persistence.Lob; -import jakarta.persistence.ManyToMany; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.MapKeyEnumerated; -import jakarta.persistence.OrderColumn; -import jakarta.persistence.Table; -import jakarta.persistence.Version; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; -import org.hibernate.annotations.ColumnDefault; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.Formula; -import org.hibernate.annotations.SoftDelete; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -@Setter -@Getter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Entity -@SoftDelete -@DynamicUpdate -@DynamicInsert -@EntityListeners(AuditingEntityListener.class) -@Table( - comment = "员工", - indexes = { - @Index(name = "idx_employee_name", columnList = "name"), - @Index(name = "idx_employee_salary", columnList = "salary"), - @Index(name = "idx_employee_active", columnList = "active") - } -) -public class Employee extends SimpleEntity { - @Column(nullable = false, length = 100, comment = "名称") - private String name; - - @Column(nullable = false, comment = "年龄") - private Integer age; - - @Column(nullable = false, comment = "角色") - @Enumerated(EnumType.STRING) - private Role role; - - @Column(unique = true, length = 50, comment = "工号") - private String code; - - @Column(nullable = false, comment = "薪资") - private BigDecimal salary; - - @Column(precision = 19, scale = 4, comment = "奖金") - private BigDecimal bonus; - - @Column(comment = "是否激活") - @ColumnDefault("true") - private Boolean active; - - @Lob - @Column(comment = "简历(大文本)") - private String resume; - - @Version - private Long version; - - @Column(insertable = false, updatable = false) - @Formula("salary + COALESCE(bonus, 0)") - private BigDecimal earnings; - - @Embedded - private Address address; - - @ManyToOne - @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) - @ToString.Exclude - private Company company; - - @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) - @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) - @ToString.Exclude - @Builder.Default - private Set skills = new HashSet<>(); - - @ElementCollection - @JoinTable(joinColumns = @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))) - @Column(comment = "兴趣") - @OrderColumn - @ToString.Exclude - @Builder.Default - private List hobbies = new ArrayList<>(); - - @ElementCollection - @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) - @Column(comment = "属性") - @Builder.Default - private Map properties = new HashMap<>(); - - @ElementCollection - @JoinTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) - @MapKeyEnumerated(EnumType.STRING) - @Column(nullable = false) - @Builder.Default - private Map connections = new HashMap<>(); - - public enum Role { - USER, - ADMIN, - } - - public enum ConnectionType { - EMAIL, - PHONE, - ADDRESS, - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Report.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Report.java deleted file mode 100644 index 05e4cf6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Report.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.SoftDelete; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -@Setter -@Getter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Entity -@SoftDelete -@DynamicUpdate -@DynamicInsert -@EntityListeners(AuditingEntityListener.class) -@Table(comment = "报告") -public class Report extends SimpleEntity { - @Column(nullable = false, comment = "分数") - @Builder.Default - private Double score = 0.0; - @Column(nullable = false, comment = "等级") - @Enumerated(EnumType.STRING) - private Level level; - - @Column(nullable = false, comment = "员工 ID") - private Long employeeId; - - public enum Level { - A, B, C, D, E - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Skill.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Skill.java deleted file mode 100644 index b65ad01..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/Skill.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; -import org.hibernate.annotations.DynamicInsert; -import org.hibernate.annotations.DynamicUpdate; -import org.hibernate.annotations.SoftDelete; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -@Setter -@Getter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Entity -@SoftDelete -@DynamicUpdate -@DynamicInsert -@EntityListeners(AuditingEntityListener.class) -@Table -public class Skill extends SimpleEntity { - @Column(nullable = false, length = 100, unique = true, comment = "技能名称") - private String name; - - @Column(length = 500, comment = "技能描述") - private String description; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/vo/EmployeeWithCompanyName.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/vo/EmployeeWithCompanyName.java deleted file mode 100644 index 773845d..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/vo/EmployeeWithCompanyName.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity.vo; - -public record EmployeeWithCompanyName( - String name, - String companyName, - Integer age, - String role -) { -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/CompanyRepository.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/CompanyRepository.java deleted file mode 100644 index 8b651c7..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/CompanyRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.repository; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company; -import org.springframework.stereotype.Repository; - -@Repository -public interface CompanyRepository extends SimpleRepository { -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/EmployeeRepository.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/EmployeeRepository.java deleted file mode 100644 index a522168..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/EmployeeRepository.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.repository; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Skill; -import java.math.BigDecimal; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.stereotype.Repository; - -@SuppressWarnings("NullableProblems") -@Repository -public interface EmployeeRepository extends SimpleRepository { - @EntityGraph(attributePaths = {"company"}) - @Override - Optional findOne(Specification specification); - - // ==================== 1. 基本字段查询 ==================== - - // 单字段精确匹配 - List findByName(String name); - - Optional findByCode(String code); - - List findByRole(Employee.Role role); - - // 布尔值查询 - List findByActiveTrue(); - - List findByActiveFalse(); - - long countByActiveTrue(); - - long countByActiveFalse(); - - // ==================== 2. 比较运算符查询 ==================== - - List findByAgeGreaterThan(Integer age); - - List findByAgeLessThan(Integer age); - - List findByAgeGreaterThanEqual(Integer age); - - List findByAgeLessThanEqual(Integer age); - - List findByAgeBetween(Integer startAge, Integer endAge); - - List findBySalaryGreaterThan(BigDecimal salary); - - List findBySalaryLessThan(BigDecimal salary); - - List findBySalaryGreaterThanEqual(BigDecimal salary); - - List findBySalaryLessThanEqual(BigDecimal salary); - - List findBySalaryBetween(BigDecimal minSalary, BigDecimal maxSalary); - - // ==================== 3. 字符串匹配查询 ==================== - - // 精确匹配 - List findByNameContaining(String name); - - List findByNameStartingWith(String prefix); - - List findByNameEndingWith(String suffix); - - List findByNameLike(String pattern); - - // 忽略大小写 - List findByNameContainingIgnoreCase(String name); - - List findByNameStartingWithIgnoreCase(String prefix); - - List findByNameEndingWithIgnoreCase(String suffix); - - List findByNameIgnoreCase(String name); - - // ==================== 4. NULL值和空值查询 ==================== - - List findByBonusIsNull(); - - List findByBonusIsNotNull(); - - List findByResumeIsNull(); - - List findByResumeIsNotNull(); - - List findByHobbiesEmpty(); - - List findByHobbiesIsNotEmpty(); - - List findBySkillsEmpty(); - - List findBySkillsIsNotEmpty(); - - // ==================== 5. 集合成员查询 (IN/NOT IN) ==================== - - List findByRoleIn(Set roles); - - List findByRoleNotIn(Set roles); - - List findByNameIn(List names); - - List findByNameNotIn(List names); - - List findByAgeIn(List ages); - - List findByAgeNotIn(List ages); - - // ==================== 6. 逻辑运算查询 (AND/OR/NOT) ==================== - - List findByNameAndRole(String name, Employee.Role role); - - List findByAgeAndActive(Integer age, Boolean active); - - List findByNameAndSalaryGreaterThan(String name, BigDecimal salary); - - List findByRoleAndActiveAndAgeGreaterThan(Employee.Role role, Boolean active, Integer age); - - List findByNameOrRole(String name, Employee.Role role); - - List findByAgeLessThanOrSalaryGreaterThan(Integer age, BigDecimal salary); - - List findByNameOrCode(String name, String code); - - List findByRoleNot(Employee.Role role); - - List findByNameNot(String name); - - // ==================== 7. 排序查询 ==================== - - List findByActiveTrueOrderByAgeAsc(); - - List findByActiveTrueOrderByAgeDesc(); - - List findByActiveTrueOrderBySalaryDesc(); - - List findByRoleOrderByAgeDescNameAsc(Employee.Role role); - - // ==================== 8. 分页查询 ==================== - - Page findByActiveTrue(Pageable pageable); - - Page findByRole(Employee.Role role, Pageable pageable); - - Page findBySalaryGreaterThan(BigDecimal salary, Pageable pageable); - - // ==================== 9. 关联查询 (JOIN) ==================== - - List findByCompany(Company company); - - List findByCompanyName(String companyName); - - List findByCompanyNameContaining(String companyName); - - List findByCompanyMembersGreaterThan(Integer members); - - List findBySkillsContaining(Skill skill); - - List findBySkillsName(String skillName); - - List findBySkillsNameContaining(String skillName); - - List findBySkillsNameIn(List skillNames); - - // ==================== 10. 嵌入式对象查询 ==================== - - List findByAddressCity(String city); - - List findByAddressCityContaining(String city); - - List findByAddressState(String state); - - List findByAddressCountry(String country); - - List findByAddressCityAndAddressState(String city, String state); - - // ==================== 11. 复合复杂查询 ==================== - - List findByNameAndRoleAndAgeGreaterThan(String name, Employee.Role role, Integer age); - - List findByRoleAndActiveTrueAndSalaryGreaterThan(Employee.Role role, BigDecimal salary); - - List findByNameContainingIgnoreCaseAndActiveTrueAndAgeBetween(String name, Integer minAge, Integer maxAge); - - List findByCompanyNameContainingAndActiveTrue(String companyName); - - List findBySkillsNameContainingAndAgeGreaterThan(String skillName, Integer age); - - // ==================== 12. DISTINCT 查询 ==================== - - List findDistinctByRole(Employee.Role role); - - // ==================== 13. TOP/LIMIT 查询 ==================== - - List findTop5BySalaryGreaterThan(BigDecimal salary); - - Optional findFirstByRoleOrderBySalaryDesc(Employee.Role role); - - // ==================== 14. LIKE 模式查询 ==================== - - List findByNameLikeIgnoreCase(String pattern); - - List findByNameStartingWithAndRole(String prefix, Employee.Role role); - - List findByNameEndingWithAndAgeLessThan(String suffix, Integer age); -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/ReportRepository.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/ReportRepository.java deleted file mode 100644 index bc5aee1..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/ReportRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.repository; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Report; -import org.springframework.stereotype.Repository; - -@Repository -public interface ReportRepository extends SimpleRepository { -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/CompanyService.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/CompanyService.java deleted file mode 100644 index 325be0b..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/CompanyService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.service; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Company; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.CompanyRepository; -import org.springframework.stereotype.Service; - -@Service -public class CompanyService extends SimpleServiceSupport { - public CompanyService(CompanyRepository repository) { - super(repository); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/EmployeeService.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/EmployeeService.java deleted file mode 100644 index 2cf1ef2..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/EmployeeService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.service; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.EmployeeRepository; -import org.springframework.stereotype.Service; - -@Service -public class EmployeeService extends SimpleServiceSupport { - public EmployeeService(EmployeeRepository repository) { - super(repository); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/ReportService.java b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/ReportService.java deleted file mode 100644 index 26d2c61..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/java/com/lanyuanxiaoyao/service/template/database/jpa/service/ReportService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.service; - -import com.lanyuanxiaoyao.service.template.database.jpa.entity.Report; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.ReportRepository; -import org.springframework.stereotype.Service; - -@Service -public class ReportService extends SimpleServiceSupport { - public ReportService(ReportRepository repository) { - super(repository); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/resources/application.yml b/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/resources/application.yml deleted file mode 100644 index e6da0be..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/test/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - profiles: - include: test - datasource: - url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 - username: test - password: test - driver-class-name: org.h2.Driver - jpa: - generate-ddl: true -fenix: - print-banner: false diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/pom.xml b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/pom.xml deleted file mode 100644 index afe7219..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - 4.0.0 - - com.lanyuanxiaoyao - spring-boot-service-template - 1.1.0-SNAPSHOT - - - spring-boot-service-template-database-xbatis - - - - com.lanyuanxiaoyao - spring-boot-service-template-database-common - - - - org.springframework.boot - spring-boot-starter-web - provided - - - - cn.xbatis - xbatis-spring-boot-starter - - - - com.lanyuanxiaoyao - spring-boot-service-template-database-common-test - test - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - package - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.projectlombok - lombok - - - - - - - \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/configuration/MybatisConfiguration.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/configuration/MybatisConfiguration.java deleted file mode 100644 index f97cf4e..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/configuration/MybatisConfiguration.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.configuration; - -import cn.xbatis.core.incrementer.GeneratorFactory; -import cn.xbatis.core.mybatis.mapper.BasicMapper; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SnowflakeIdGenerator; -import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@MapperScan(basePackageClasses = MybatisBasicMapper.class, markerInterface = BasicMapper.class) -public class MybatisConfiguration { - static { - GeneratorFactory.register("snowflake", new SnowflakeIdGenerator()); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/SimpleControllerSupport.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/SimpleControllerSupport.java deleted file mode 100644 index b524769..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/SimpleControllerSupport.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.controller; - -import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.controller.SimpleController; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SimpleEntity; -import com.lanyuanxiaoyao.service.template.database.xbatis.service.SimpleServiceSupport; -import java.util.function.Function; -import lombok.extern.slf4j.Slf4j; -import org.springframework.transaction.annotation.Transactional; -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; - -/** - * 简单控制器支持类,提供基础的CRUD操作实现 - *

- * 该类实现了基本的增删改查功能,通过泛型支持不同类型的数据转换。 - * 子类需要实现对应的Mapper函数来完成实体类与传输对象之间的转换。 - *

- * - *

设计特点

- *
    - *
  • 泛型设计,支持任意实体类型和数据转换
  • - *
  • 统一的异常处理和事务管理
  • - *
  • 支持条件查询、分页查询和详情查询
  • - *
  • 提供抽象的Mapper方法,便于子类实现数据转换逻辑
  • - *
- * - *

使用说明

- *

子类需要实现以下抽象方法:

- *
    - *
  • saveItemMapper(): 保存项到实体的转换函数
  • - *
  • listItemMapper(): 实体到列表项的转换函数
  • - *
  • detailItemMapper(): 实体到详情项的转换函数
  • - *
- * - * @param 实体类型,必须继承SimpleEntity - * @param 保存项类型 - * @param 列表项类型 - * @param 详情项类型 - */ -@Slf4j -public abstract class SimpleControllerSupport implements SimpleController { - protected final SimpleServiceSupport service; - - /** - * 构造函数 - * - * @param service 简单服务支持类实例 - */ - public SimpleControllerSupport(SimpleServiceSupport service) { - this.service = service; - } - - /** - * 保存实体对象 - *

- * 将保存项转换为实体对象后保存,返回保存后的实体ID。 - * 支持新增和更新操作,通过事务保证数据一致性。 - *

- * - * @param item 需要保存的项 - * @return 返回保存后的实体ID响应对象,格式:{status: 0, message: "OK", data: 实体ID} - * @throws Exception 保存过程中可能抛出的异常 - */ - @Transactional(rollbackFor = Throwable.class) - @PostMapping(SAVE) - @Override - public GlobalResponse save(@RequestBody SAVE_ITEM item) throws Exception { - var mapper = saveItemMapper(); - return GlobalResponse.responseSuccess(service.save(mapper.apply(item))); - } - - /** - * 获取所有实体列表 - *

- * 查询所有记录,不带任何过滤条件,返回分页格式的数据。 - * 将实体对象转换为列表项对象后返回。 - *

- * - * @return 返回实体列表响应对象,格式:{status: 0, message: "OK", data: {items: [...], total: total}} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @GetMapping(LIST) - @Override - public GlobalResponse> list() throws Exception { - var mapper = listItemMapper(); - var result = service.list(); - return GlobalResponse.responseListData( - result - .stream() - .map(entity -> { - try { - return mapper.apply(entity); - } catch (Exception e) { - throw new RuntimeException(e); - } - }) - .toList(), - result.size() - ); - } - - /** - * 根据查询条件获取实体列表 - *

- * 支持复杂的查询条件、排序和分页,返回符合条件的数据。 - * 将实体对象转换为列表项对象后返回。 - *

- * - * @param query 查询条件对象,包含过滤条件、排序规则和分页信息 - * @return 返回符合条件的实体列表响应对象,格式:{status: 0, message: "OK", data: {items: [...], total: total}} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @PostMapping(LIST) - @Override - public GlobalResponse> list(@RequestBody Query query) throws Exception { - if (ObjectHelper.isNull(query)) { - return GlobalResponse.responseListData(); - } - var mapper = listItemMapper(); - var result = service.list(query); - return GlobalResponse.responseListData( - result.items() - .stream() - .map(entity -> { - try { - return mapper.apply(entity); - } catch (Exception e) { - throw new RuntimeException(e); - } - }) - .toList(), - result.total() - ); - } - - /** - * 根据ID获取实体详情 - *

- * 根据主键ID查询单条记录的详细信息,转换为详情项对象后返回。 - * 如果记录不存在则抛出异常。 - *

- * - * @param id 实体主键ID - * @return 返回实体详情响应对象,格式:{status: 0, message: "OK", data: 详情数据} - * @throws Exception 查询过程中可能抛出的异常 - */ - @Transactional(readOnly = true) - @GetMapping(DETAIL) - @Override - public GlobalResponse detail(@PathVariable("id") Long id) throws Exception { - var mapper = detailItemMapper(); - return GlobalResponse.responseSuccess(mapper.apply(service.detailOrThrow(id))); - } - - /** - * 根据ID删除实体对象 - *

- * 根据主键ID删除指定的记录,执行成功后返回成功响应。 - * 通过事务保证删除操作的一致性。 - *

- * - * @param id 需要删除的实体主键ID - * @return 返回删除结果响应对象,格式:{status: 0, message: "OK", data: null} - * @throws Exception 删除过程中可能抛出的异常 - */ - @Transactional(rollbackFor = Throwable.class) - @GetMapping(REMOVE) - @Override - public GlobalResponse remove(@PathVariable("id") Long id) throws Exception { - service.remove(id); - return GlobalResponse.responseSuccess(); - } - - /** - * 保存项映射器,将保存项转换为实体对象 - *

- * 子类需要实现此方法,定义保存项到实体的转换逻辑。 - *

- * - * @return Function 保存项到实体的转换函数 - */ - protected abstract Function saveItemMapper(); - - /** - * 列表项映射器,将实体对象转换为列表项 - *

- * 子类需要实现此方法,定义实体到列表项的转换逻辑。 - *

- * - * @return Function 实体到列表项的转换函数 - */ - protected abstract Function listItemMapper(); - - /** - * 详情项映射器,将实体对象转换为详情项 - *

- * 子类需要实现此方法,定义实体到详情项的转换逻辑。 - *

- * - * @return Function 实体到详情项的转换函数 - */ - protected abstract Function detailItemMapper(); - - public interface Mapper { - T map(S source) throws Exception; - } -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/IdOnlyEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/IdOnlyEntity.java deleted file mode 100644 index 44eeaa4..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/IdOnlyEntity.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.db.IdAutoType; -import cn.xbatis.db.annotations.TableId; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString -@FieldNameConstants -public class IdOnlyEntity { - @TableId(value = IdAutoType.GENERATOR, generator = "snowflake") - private Long id; -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/LogicDeleteEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/LogicDeleteEntity.java deleted file mode 100644 index a9df500..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/LogicDeleteEntity.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.db.annotations.LogicDelete; -import cn.xbatis.db.annotations.LogicDeleteTime; -import java.time.LocalDateTime; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString -@FieldNameConstants -public class LogicDeleteEntity extends IdOnlyEntity { - @LogicDelete - private Boolean deleted = false; - @LogicDeleteTime - private LocalDateTime deletedTime; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SimpleEntity.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SimpleEntity.java deleted file mode 100644 index 12fb23f..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SimpleEntity.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.db.annotations.TableField; -import java.time.LocalDateTime; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -public class SimpleEntity extends LogicDeleteEntity { - @TableField(defaultValue = "{NOW}", defaultValueFillAlways = true) - private LocalDateTime createdTime; - @TableField(defaultValue = "{NOW}", defaultValueFillAlways = true, updateDefaultValue = "{NOW}", updateDefaultValueFillAlways = true) - private LocalDateTime modifiedTime; -} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SnowflakeIdGenerator.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SnowflakeIdGenerator.java deleted file mode 100644 index 80969b6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/SnowflakeIdGenerator.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.core.incrementer.Generator; -import com.lanyuanxiaoyao.service.template.database.common.helper.SnowflakeHelper; - -public class SnowflakeIdGenerator implements Generator { - @Override - public Long nextId(Class entity) { - return SnowflakeHelper.next(); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/mapper/MybatisBasicMapper.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/mapper/MybatisBasicMapper.java deleted file mode 100644 index 9e1a151..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/mapper/MybatisBasicMapper.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.mapper; - -import cn.xbatis.core.mybatis.mapper.BasicMapper; - -public interface MybatisBasicMapper extends BasicMapper { -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/SimpleServiceSupport.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/SimpleServiceSupport.java deleted file mode 100644 index 9b8c0e4..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/main/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/SimpleServiceSupport.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.service; - -import cn.xbatis.core.mybatis.mapper.context.Pager; -import cn.xbatis.core.sql.MybatisCmdFactory; -import cn.xbatis.core.sql.executor.chain.QueryChain; -import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.entity.Page; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.common.exception.IdNotFoundException; -import com.lanyuanxiaoyao.service.template.database.common.service.QueryParser; -import com.lanyuanxiaoyao.service.template.database.common.service.SimpleService; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.SimpleEntity; -import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper; -import db.sql.api.cmd.LikeMode; -import db.sql.api.impl.cmd.basic.OrderByDirection; -import db.sql.api.impl.cmd.struct.Where; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import lombok.extern.slf4j.Slf4j; -import org.mapstruct.Named; -import org.springframework.transaction.annotation.Transactional; - -@Slf4j -public abstract class SimpleServiceSupport implements SimpleService { - private static final int DEFAULT_PAGE_INDEX = 1; - private static final int DEFAULT_PAGE_SIZE = 10; - - protected final MybatisBasicMapper mapper; - private final Class target; - - public SimpleServiceSupport(Class target, MybatisBasicMapper mapper) { - this.target = target; - this.mapper = mapper; - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public Long save(ENTITY entity) { - mapper.saveOrUpdate(entity); - return entity.getId(); - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void save(Iterable entities) { - mapper.saveOrUpdate(entities); - } - - @Transactional(readOnly = true) - @Override - public Long count() { - return (long) mapper.countAll(target); - } - - @Transactional(readOnly = true) - @Override - public List list() { - return mapper.listAll(target); - } - - @Transactional(readOnly = true) - @Override - public List list(Set ids) { - return mapper.listByIds(target, ids); - } - - protected void commonPredicates(Where where) { - } - - @Transactional(readOnly = true) - @Override - public Page list(Query query) { - var chain = QueryChain.of(mapper, target); - var factory = chain.$(); - - var paging = Pager.of(DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE); - if (ObjectHelper.isNotNull(query.page())) { - var index = Math.max(ObjectHelper.defaultIfNull(query.page().index(), DEFAULT_PAGE_INDEX), 1); - var size = Math.max(ObjectHelper.defaultIfNull(query.page().size(), DEFAULT_PAGE_SIZE), 1); - paging = Pager.of(index, size); - } - - if (ObjectHelper.isNotEmpty(query.sort())) { - query.sort().forEach(sort -> chain.orderBy(OrderByDirection.valueOf(sort.direction().name()), sort.column())); - } - - var where = chain.where(); - commonPredicates(where); - new XBatisQueryParser<>(query.query(), where, target, factory).build(); - - var pager = chain.paging(paging); - - return new Page<>(pager.getResults(), pager.getTotal()); - } - - private Optional detailOptional(Long id) { - if (ObjectHelper.isNull(id)) { - return Optional.empty(); - } - return mapper.getOptionalById(target, id); - } - - @Named("detail") - @Transactional(readOnly = true) - @Override - public ENTITY detail(Long id) { - return detailOptional(id).orElse(null); - } - - @Named("detailOrThrow") - @Transactional(readOnly = true) - @Override - public ENTITY detailOrThrow(Long id) { - return detailOptional(id).orElseThrow(() -> new IdNotFoundException(id)); - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void remove(Long id) { - mapper.deleteById(target, id); - } - - @Transactional(rollbackFor = Throwable.class) - @Override - public void remove(Set ids) { - mapper.deleteByIds(target, ids); - } - - private static final class XBatisQueryParser extends QueryParser { - private final Class target; - private final MybatisCmdFactory factory; - - private XBatisQueryParser(Query.Queryable queryable, Where where, Class target, MybatisCmdFactory factory) { - super(queryable, where); - this.target = target; - this.factory = factory; - } - - @Override - protected void nullEqual(Query.Queryable queryable, Where where) { - queryable.nullEqual().forEach(column -> where.isNull(factory.field(target, column))); - } - - @Override - protected void notNullEqual(Query.Queryable queryable, Where where) { - queryable.notNullEqual().forEach(column -> where.isNotNull(factory.field(target, column))); - } - - @Override - protected void empty(Query.Queryable queryable, Where where) { - throw new UnsupportedOperationException(); - } - - @Override - protected void notEmpty(Query.Queryable queryable, Where where) { - throw new UnsupportedOperationException(); - } - - @Override - protected void equal(Query.Queryable queryable, Where where) { - queryable.equal().forEach((column, value) -> where.eq(factory.field(target, column), value)); - } - - @Override - protected void notEqual(Query.Queryable queryable, Where where) { - queryable.notEqual().forEach((column, value) -> where.ne(factory.field(target, column), value)); - } - - @Override - protected void like(Query.Queryable queryable, Where where) { - queryable.like().forEach((column, value) -> where.like(LikeMode.NONE, factory.field(target, column), value)); - } - - @Override - protected void notLike(Query.Queryable queryable, Where where) { - queryable.notLike().forEach((column, value) -> where.notLike(LikeMode.NONE, factory.field(target, column), value)); - } - - @Override - protected void contain(Query.Queryable queryable, Where where) { - queryable.contain().forEach((column, value) -> where.like(factory.field(target, column), value)); - } - - @Override - protected void notContain(Query.Queryable queryable, Where where) { - queryable.notContain().forEach((column, value) -> where.notLike(factory.field(target, column), value)); - } - - @Override - protected void startWith(Query.Queryable queryable, Where where) { - queryable.startWith().forEach((column, value) -> where.like(LikeMode.RIGHT, factory.field(target, column), value)); - } - - @Override - protected void notStartWith(Query.Queryable queryable, Where where) { - queryable.notStartWith().forEach((column, value) -> where.notLike(LikeMode.RIGHT, factory.field(target, column), value)); - } - - @Override - protected void endWith(Query.Queryable queryable, Where where) { - queryable.endWith().forEach((column, value) -> where.like(LikeMode.LEFT, factory.field(target, column), value)); - } - - @Override - protected void notEndWith(Query.Queryable queryable, Where where) { - queryable.notEndWith().forEach((column, value) -> where.notLike(LikeMode.LEFT, factory.field(target, column), value)); - } - - @Override - protected void great(Query.Queryable queryable, Where where) { - queryable.great().forEach((column, value) -> where.gt(factory.field(target, column), value)); - } - - @Override - protected void less(Query.Queryable queryable, Where where) { - queryable.less().forEach((column, value) -> where.lt(factory.field(target, column), value)); - } - - @Override - protected void greatEqual(Query.Queryable queryable, Where where) { - queryable.greatEqual().forEach((column, value) -> where.gte(factory.field(target, column), value)); - } - - @Override - protected void lessEqual(Query.Queryable queryable, Where where) { - queryable.lessEqual().forEach((column, value) -> where.lte(factory.field(target, column), value)); - } - - @Override - protected void inside(Query.Queryable queryable, Where where) { - queryable.inside() - .entrySet() - .stream() - .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) - .forEach(entry -> where.in(factory.field(target, entry.getKey()), entry.getValue())); - } - - @Override - protected void notInside(Query.Queryable queryable, Where where) { - queryable.notInside() - .entrySet() - .stream() - .filter(entry -> ObjectHelper.isNotEmpty(entry.getValue())) - .forEach(entry -> where.notIn(factory.field(target, entry.getKey()), entry.getValue())); - } - - @Override - protected void between(Query.Queryable queryable, Where where) { - queryable.between().forEach((column, value) -> where.between(factory.field(target, column), value.start(), value.end())); - } - - @Override - protected void notBetween(Query.Queryable queryable, Where where) { - queryable.notBetween().forEach((column, value) -> where.notBetween(factory.field(target, column), value.start(), value.end())); - } - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql deleted file mode 100644 index 51fc51e..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql +++ /dev/null @@ -1,22 +0,0 @@ -create table if not exists Company -( - id bigint primary key, - name varchar(255) not null, - members int not null, - created_time timestamp not null, - modified_time timestamp not null, - deleted tinyint not null default 0, - deleted_time timestamp -); - -create table if not exists Employee -( - id bigint primary key, - name varchar(255) not null, - age int not null, - company_id bigint not null, - created_time timestamp not null, - modified_time timestamp not null, - deleted tinyint not null default 0, - deleted_time timestamp -); diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/TestApplication.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/TestApplication.java deleted file mode 100644 index 09e55a6..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/TestApplication.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis; - -import cn.xbatis.core.sql.executor.chain.QueryChain; -import com.lanyuanxiaoyao.service.template.database.common.test.AbstractTestApplication; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.vo.EmployeeWithCompanyName; -import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper; -import db.sql.api.cmd.LikeMode; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.util.Assert; - -@Slf4j -@RequiredArgsConstructor -@MapperScan("com.lanyuanxiaoyao.service.template.database.xbatis.mapper") -@SpringBootApplication -public class TestApplication extends AbstractTestApplication { - private final MybatisBasicMapper mapper; - - public static void main(String[] args) { - SpringApplication.run(TestApplication.class, args); - } - - @EventListener(ApplicationReadyEvent.class) - public void runTests() { - testCrud(); - testDelete(); - testQuery(); - - System.exit(0); - } - - private void testDelete() { - formatLog("Delete"); - saveItem("company", randomCompany()); - saveItem("company", randomCompany()); - mapper.deleteAll(Company.class); - } - - private void testQuery() { - formatLog("Added"); - var company1 = Company.builder().name(randomString(5)).members(randomInt(100)).build(); - mapper.saveOrUpdate(company1); - var company2 = Company.builder().name(randomString(5)).members(randomInt(100)).build(); - mapper.saveOrUpdate(company2); - var employee1 = Employee.builder().name("Tom").age(randomInt(100)).companyId(company1.getId()).build(); - mapper.saveOrUpdate(employee1); - var employee2 = Employee.builder().name(randomString(10)).age(randomInt(100)).companyId(company2.getId()).build(); - mapper.saveOrUpdate(employee2); - - formatLog("Query"); - var employees1 = QueryChain.of(mapper, Employee.class) - .isNotNull(Employee::getName) - .eq(Employee::getName, "Tom") - .like(Employee::getName, "To") - .like(LikeMode.RIGHT, Employee::getName, "To") - .like(LikeMode.LEFT, Employee::getName, "om") - .lt(Employee::getAge, 200) - .gt(Employee::getAge, 0) - .in(Employee::getName, "Tom", "Mike") - .between(Employee::getAge, 0, 200) - .list(); - Assert.isTrue(employees1.size() == 1, "查询数量错误"); - - formatLog("Query Join"); - var employees2 = QueryChain.of(mapper, Employee.class) - .select(Employee::getName, Employee::getAge) - .select(Company::getId, c -> c.as(EmployeeWithCompanyName::getCompanyName)) - .leftJoin(Employee.class, Company.class, on -> on.eq(Employee::getCompanyId, Company::getId).gt(Company::getMembers, 0)) - .eq(Employee::getName, "Tom") - .lt(Company::getMembers, 200) - .returnType(EmployeeWithCompanyName.class) - .list(); - Assert.isTrue(employees2.size() == 1, "查询数量错误"); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/CompanyController.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/CompanyController.java deleted file mode 100644 index 6f13f4d..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/controller/CompanyController.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.controller; - -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company; -import com.lanyuanxiaoyao.service.template.database.xbatis.service.CompanyService; -import java.time.LocalDateTime; -import java.util.function.Function; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("company") -public class CompanyController extends SimpleControllerSupport { - public CompanyController(CompanyService service) { - super(service); - } - - @Override - protected Function saveItemMapper() { - return item -> { - var company = new Company(); - company.setId(item.id()); - company.setName(item.name()); - company.setMembers(item.members()); - return company; - }; - } - - @Override - protected Function listItemMapper() { - return company -> new ListItem( - company.getId(), - company.getName(), - company.getMembers() - ); - } - - @Override - protected Function detailItemMapper() { - return company -> new DetailItem( - company.getId(), - company.getName(), - company.getMembers(), - company.getCreatedTime(), - company.getModifiedTime() - ); - } - - public record SaveItem( - Long id, - String name, - Integer members - ) { - } - - public record ListItem( - Long id, - String name, - Integer members - ) { - } - - public record DetailItem( - Long id, - String name, - Integer members, - LocalDateTime createdTime, - LocalDateTime modifiedTime - ) { - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Company.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Company.java deleted file mode 100644 index 5872e84..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Company.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.db.annotations.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Table -public class Company extends SimpleEntity { - private String name; - private Integer members; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Employee.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Employee.java deleted file mode 100644 index 61b4a80..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/Employee.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity; - -import cn.xbatis.db.annotations.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -@AllArgsConstructor -@NoArgsConstructor -@Builder -@Table -public class Employee extends SimpleEntity { - private String name; - private Integer age; - - private Long companyId; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/vo/EmployeeWithCompanyName.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/vo/EmployeeWithCompanyName.java deleted file mode 100644 index b93250e..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/entity/vo/EmployeeWithCompanyName.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.entity.vo; - -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.FieldNameConstants; - -@Getter -@Setter -@ToString(callSuper = true) -@FieldNameConstants -public class EmployeeWithCompanyName { - private String name; - private Integer age; - private String companyName; -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/CompanyService.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/CompanyService.java deleted file mode 100644 index 8ec6159..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/CompanyService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.service; - -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Company; -import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper; -import org.springframework.stereotype.Service; - -@Service -public class CompanyService extends SimpleServiceSupport { - public CompanyService(MybatisBasicMapper mapper) { - super(Company.class, mapper); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/EmployeeService.java b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/EmployeeService.java deleted file mode 100644 index 0a20962..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/java/com/lanyuanxiaoyao/service/template/database/xbatis/service/EmployeeService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lanyuanxiaoyao.service.template.database.xbatis.service; - -import com.lanyuanxiaoyao.service.template.database.xbatis.entity.Employee; -import com.lanyuanxiaoyao.service.template.database.xbatis.mapper.MybatisBasicMapper; -import org.springframework.stereotype.Service; - -@Service -public class EmployeeService extends SimpleServiceSupport { - public EmployeeService(MybatisBasicMapper mapper) { - super(Employee.class, mapper); - } -} diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/resources/application.yml b/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/resources/application.yml deleted file mode 100644 index b8a7106..0000000 --- a/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/resources/application.yml +++ /dev/null @@ -1,11 +0,0 @@ -spring: - profiles: - include: test - datasource: - url: "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL;DATABASE_TO_LOWER=TRUE;INIT=runscript from '/Users/lanyuanxiaoyao/Project/IdeaProjects/spring-boot-service-template/spring-boot-service-template-database/spring-boot-service-template-database-xbatis/src/test/initial.sql'" - username: test - password: test - driver-class-name: org.h2.Driver -mybatis: - configuration: - banner: false \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/configuration/QueryDSLConfiguration.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/configuration/QueryDSLConfiguration.java similarity index 83% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/configuration/QueryDSLConfiguration.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/configuration/QueryDSLConfiguration.java index c094527..7943655 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/configuration/QueryDSLConfiguration.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/configuration/QueryDSLConfiguration.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.configuration; +package com.lanyuanxiaoyao.service.template.database.configuration; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; @@ -11,4 +11,4 @@ public class QueryDSLConfiguration { public JPAQueryFactory jpaQueryFactory(EntityManager manager) { return new JPAQueryFactory(manager); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/QueryController.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/QueryController.java similarity index 91% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/QueryController.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/QueryController.java index 75cc7cb..7c0eb81 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/QueryController.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/QueryController.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.controller; +package com.lanyuanxiaoyao.service.template.database.controller; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; +import com.lanyuanxiaoyao.service.template.database.entity.GlobalResponse; +import com.lanyuanxiaoyao.service.template.database.entity.Query; /** * 查询控制器接口,用于定义统一的查询实体详情和列表的接口规范 diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/RemoveController.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/RemoveController.java similarity index 83% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/RemoveController.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/RemoveController.java index bbfb7e6..44ce9ea 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/RemoveController.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/RemoveController.java @@ -1,6 +1,6 @@ -package com.lanyuanxiaoyao.service.template.database.common.controller; +package com.lanyuanxiaoyao.service.template.database.controller; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; +import com.lanyuanxiaoyao.service.template.database.entity.GlobalResponse; /** * 删除控制器接口,用于定义统一的删除实体对象的接口规范 diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SaveController.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SaveController.java similarity index 85% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SaveController.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SaveController.java index d6bef16..daccebc 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SaveController.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SaveController.java @@ -1,6 +1,6 @@ -package com.lanyuanxiaoyao.service.template.database.common.controller; +package com.lanyuanxiaoyao.service.template.database.controller; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; +import com.lanyuanxiaoyao.service.template.database.entity.GlobalResponse; /** * 保存控制器接口,用于定义统一的保存实体对象的接口规范 diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SimpleController.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleController.java similarity index 69% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SimpleController.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleController.java index 3b9872a..936374c 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/controller/SimpleController.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleController.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.controller; +package com.lanyuanxiaoyao.service.template.database.controller; public interface SimpleController extends SaveController, QueryController, RemoveController { -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/SimpleControllerSupport.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleControllerSupport.java similarity index 93% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/SimpleControllerSupport.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleControllerSupport.java index fd0cb88..c837832 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/controller/SimpleControllerSupport.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/controller/SimpleControllerSupport.java @@ -1,11 +1,10 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.controller; +package com.lanyuanxiaoyao.service.template.database.controller; import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.controller.SimpleController; -import com.lanyuanxiaoyao.service.template.database.common.entity.GlobalResponse; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.SimpleEntity; -import com.lanyuanxiaoyao.service.template.database.jpa.service.SimpleServiceSupport; +import com.lanyuanxiaoyao.service.template.database.entity.GlobalResponse; +import com.lanyuanxiaoyao.service.template.database.entity.Query; +import com.lanyuanxiaoyao.service.template.database.entity.SimpleEntity; +import com.lanyuanxiaoyao.service.template.database.service.SimpleServiceSupport; import java.util.function.Function; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/GlobalResponse.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/GlobalResponse.java similarity index 99% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/GlobalResponse.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/GlobalResponse.java index eeeba43..90d50b2 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/GlobalResponse.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/GlobalResponse.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import java.util.List; import java.util.Map; @@ -356,4 +356,4 @@ public record GlobalResponse(Integer status, String message, T data) { */ public record DetailItem(T item) { } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/IdOnlyEntity.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/IdOnlyEntity.java similarity index 95% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/IdOnlyEntity.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/IdOnlyEntity.java index 266653f..72bef8e 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/IdOnlyEntity.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/IdOnlyEntity.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Page.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Page.java similarity index 92% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Page.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Page.java index 046a007..c5d887b 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Page.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Page.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import java.util.List; @@ -28,4 +28,4 @@ import java.util.List; * @param total 总记录数,用于计算总页数和显示分页信息 */ public record Page(List items, long total) { -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Query.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Query.java similarity index 99% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Query.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Query.java index b3f8ec1..c7e6d24 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/entity/Query.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/Query.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import java.io.Serializable; import java.util.List; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SimpleEntity.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SimpleEntity.java similarity index 96% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SimpleEntity.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SimpleEntity.java index c37f8fd..0ca1a51 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SimpleEntity.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SimpleEntity.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeId.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeId.java similarity index 84% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeId.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeId.java index 001e48b..8a2a929 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeId.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeId.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; +package com.lanyuanxiaoyao.service.template.database.entity; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -10,4 +10,4 @@ import org.hibernate.annotations.IdGeneratorType; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface SnowflakeId { -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeIdGenerator.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeIdGenerator.java similarity index 77% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeIdGenerator.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeIdGenerator.java index 867090b..acd7791 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/entity/SnowflakeIdGenerator.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/entity/SnowflakeIdGenerator.java @@ -1,6 +1,6 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.entity; +package com.lanyuanxiaoyao.service.template.database.entity; -import com.lanyuanxiaoyao.service.template.database.common.helper.SnowflakeHelper; +import com.lanyuanxiaoyao.service.template.database.helper.SnowflakeHelper; import java.io.Serializable; import lombok.extern.slf4j.Slf4j; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -17,4 +17,4 @@ public class SnowflakeIdGenerator implements IdentifierGenerator { throw new RuntimeException(e); } } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/IdNotFoundException.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/IdNotFoundException.java similarity index 68% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/IdNotFoundException.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/IdNotFoundException.java index 1248096..2cf6cc8 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/IdNotFoundException.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/IdNotFoundException.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.exception; +package com.lanyuanxiaoyao.service.template.database.exception; public class IdNotFoundException extends RuntimeException { public IdNotFoundException(Long id) { super("ID为 %d 的资源不存在".formatted(id)); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotCollectionException.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotCollectionException.java similarity index 70% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotCollectionException.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotCollectionException.java index 681a86f..216f8d5 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotCollectionException.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotCollectionException.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.exception; +package com.lanyuanxiaoyao.service.template.database.exception; public class NotCollectionException extends RuntimeException { public NotCollectionException(String variable) { super("变量 %s 不是集合".formatted(variable)); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotComparableException.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotComparableException.java similarity index 70% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotComparableException.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotComparableException.java index 71876ca..cfcd622 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotComparableException.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotComparableException.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.exception; +package com.lanyuanxiaoyao.service.template.database.exception; public class NotComparableException extends RuntimeException { public NotComparableException(String variable) { super("变量 %s 不能比较".formatted(variable)); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotStringException.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotStringException.java similarity index 70% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotStringException.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotStringException.java index 80ca6c8..a22ed1c 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/exception/NotStringException.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/exception/NotStringException.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.exception; +package com.lanyuanxiaoyao.service.template.database.exception; public class NotStringException extends RuntimeException { public NotStringException(String variable) { super("变量 %s 不是字符串".formatted(variable)); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/helper/DatabaseHelper.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/DatabaseHelper.java similarity index 96% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/helper/DatabaseHelper.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/DatabaseHelper.java index fd155ba..50035bc 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/helper/DatabaseHelper.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/DatabaseHelper.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.helper; +package com.lanyuanxiaoyao.service.template.database.helper; import jakarta.persistence.Entity; import java.io.IOException; @@ -115,7 +115,7 @@ public class DatabaseHelper { package %s.repository; import %s; - import com.lanyuanxiaoyao.service.template.repository.SimpleRepository; + import com.lanyuanxiaoyao.service.template.database.repository.SimpleRepository; import org.springframework.stereotype.Repository; @Repository @@ -134,7 +134,7 @@ public class DatabaseHelper { import %s; import %s.repository.%sRepository; - import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport; + import com.lanyuanxiaoyao.service.template.database.service.SimpleServiceSupport; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -158,7 +158,7 @@ public class DatabaseHelper { import %s; import %s.service.%sService; - import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport; + import com.lanyuanxiaoyao.service.template.database.controller.SimpleControllerSupport; import java.util.function.Function; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; @@ -197,7 +197,7 @@ public class DatabaseHelper { } } - """.formatted(projectRootPackage, className, projectRootPackage, name, camelConvert(name), name, name, name, name, name, name, name, name, name, name)); + """.formatted(projectRootPackage, className, projectRootPackage, name, camelConvert(name), name, name, name, name, name, name, name, name, name, name, name)); } } catch (ClassNotFoundException e) { throw new RuntimeException("Failed to load entity class: " + className, e); diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/helper/SnowflakeHelper.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/SnowflakeHelper.java similarity index 95% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/helper/SnowflakeHelper.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/SnowflakeHelper.java index 003e13d..b0ab22e 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/helper/SnowflakeHelper.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/helper/SnowflakeHelper.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.helper; +package com.lanyuanxiaoyao.service.template.database.helper; import java.time.Instant; @@ -65,4 +65,4 @@ public class SnowflakeHelper { private static long nowTimestamp() { return Instant.now().toEpochMilli(); } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/SimpleRepository.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/repository/SimpleRepository.java similarity index 98% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/SimpleRepository.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/repository/SimpleRepository.java index 3681ee3..a2ce74c 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/repository/SimpleRepository.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/repository/SimpleRepository.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.repository; +package com.lanyuanxiaoyao.service.template.database.repository; import com.blinkfox.fenix.jpa.FenixJpaRepository; import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryParser.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryParser.java similarity index 96% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryParser.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryParser.java index 4733411..8e316f9 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryParser.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryParser.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.service; +package com.lanyuanxiaoyao.service.template.database.service; import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; +import com.lanyuanxiaoyao.service.template.database.entity.Query; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; @@ -125,4 +125,4 @@ public abstract class QueryParser { notBetween(queryable, container); } } -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryService.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryService.java similarity index 92% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryService.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryService.java index 5ac7899..e4b3ae6 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/QueryService.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/QueryService.java @@ -1,7 +1,7 @@ -package com.lanyuanxiaoyao.service.template.database.common.service; +package com.lanyuanxiaoyao.service.template.database.service; -import com.lanyuanxiaoyao.service.template.database.common.entity.Page; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; +import com.lanyuanxiaoyao.service.template.database.entity.Page; +import com.lanyuanxiaoyao.service.template.database.entity.Query; import java.util.List; import java.util.Set; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/RemoveService.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/RemoveService.java similarity index 93% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/RemoveService.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/RemoveService.java index c72ecd4..c1c991b 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/RemoveService.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/RemoveService.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.service; +package com.lanyuanxiaoyao.service.template.database.service; import java.util.Set; diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SaveService.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SaveService.java similarity index 94% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SaveService.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SaveService.java index dc74427..def7f69 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SaveService.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SaveService.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.service; +package com.lanyuanxiaoyao.service.template.database.service; /** * 保存服务接口,用于定义统一的保存实体对象的服务规范 diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SimpleService.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleService.java similarity index 61% rename from spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SimpleService.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleService.java index 3dd6a97..226982e 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-common/src/main/java/com/lanyuanxiaoyao/service/template/database/common/service/SimpleService.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleService.java @@ -1,4 +1,4 @@ -package com.lanyuanxiaoyao.service.template.database.common.service; +package com.lanyuanxiaoyao.service.template.database.service; public interface SimpleService extends SaveService, QueryService, RemoveService { -} +} \ No newline at end of file diff --git a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/service/SimpleServiceSupport.java b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleServiceSupport.java similarity index 95% rename from spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/service/SimpleServiceSupport.java rename to spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleServiceSupport.java index ddccaf5..8cc8762 100644 --- a/spring-boot-service-template-database/spring-boot-service-template-database-jpa/src/main/java/com/lanyuanxiaoyao/service/template/database/jpa/service/SimpleServiceSupport.java +++ b/spring-boot-service-template-database/src/main/java/com/lanyuanxiaoyao/service/template/database/service/SimpleServiceSupport.java @@ -1,17 +1,15 @@ -package com.lanyuanxiaoyao.service.template.database.jpa.service; +package com.lanyuanxiaoyao.service.template.database.service; import com.lanyuanxiaoyao.service.template.common.helper.ObjectHelper; -import com.lanyuanxiaoyao.service.template.database.common.entity.Page; -import com.lanyuanxiaoyao.service.template.database.common.entity.Query; -import com.lanyuanxiaoyao.service.template.database.common.exception.IdNotFoundException; -import com.lanyuanxiaoyao.service.template.database.common.exception.NotCollectionException; -import com.lanyuanxiaoyao.service.template.database.common.exception.NotComparableException; -import com.lanyuanxiaoyao.service.template.database.common.exception.NotStringException; -import com.lanyuanxiaoyao.service.template.database.common.service.QueryParser; -import com.lanyuanxiaoyao.service.template.database.common.service.SimpleService; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.IdOnlyEntity; -import com.lanyuanxiaoyao.service.template.database.jpa.entity.SimpleEntity; -import com.lanyuanxiaoyao.service.template.database.jpa.repository.SimpleRepository; +import com.lanyuanxiaoyao.service.template.database.entity.Page; +import com.lanyuanxiaoyao.service.template.database.entity.Query; +import com.lanyuanxiaoyao.service.template.database.exception.IdNotFoundException; +import com.lanyuanxiaoyao.service.template.database.exception.NotCollectionException; +import com.lanyuanxiaoyao.service.template.database.exception.NotComparableException; +import com.lanyuanxiaoyao.service.template.database.exception.NotStringException; +import com.lanyuanxiaoyao.service.template.database.entity.IdOnlyEntity; +import com.lanyuanxiaoyao.service.template.database.entity.SimpleEntity; +import com.lanyuanxiaoyao.service.template.database.repository.SimpleRepository; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Path;