From d5c7ab0f537a81fbb60cfcf89b99886e0a594bc9 Mon Sep 17 00:00:00 2001 From: Guwan Date: Thu, 17 Apr 2025 23:25:50 +0800 Subject: [PATCH] cs --- .../backend/MergeStrategy/LambdaUtils.java | 102 -------- .../JoinBuilder.java | 245 +++++------------- .../backend/jpaTest/EmployeeController.java | 25 +- .../backend/jpaTest/EmployeeRepository.java | 1 + .../backend/jpaTest/EmployeeService.java | 98 ++----- .../jpaTest/{ => domain}/Department.java | 2 +- .../jpaTest/{ => domain}/Employee.java | 2 +- .../jpaTest/{ => domain}/EmployeeDTO.java | 2 +- .../backend/jpaTest/{ => domain}/Project.java | 2 +- .../jpaTest/mapper/QueryResultMapper.java | 140 ---------- .../backend/util/DtoGeneratorExample.java | 14 + .../guwan/backend/util/DtoGeneratorUtil.java | 57 ++++ 12 files changed, 173 insertions(+), 517 deletions(-) delete mode 100644 src/main/java/com/guwan/backend/MergeStrategy/LambdaUtils.java rename src/main/java/com/guwan/backend/{MergeStrategy => builder}/JoinBuilder.java (60%) rename src/main/java/com/guwan/backend/jpaTest/{ => domain}/Department.java (90%) rename src/main/java/com/guwan/backend/jpaTest/{ => domain}/Employee.java (93%) rename src/main/java/com/guwan/backend/jpaTest/{ => domain}/EmployeeDTO.java (95%) rename src/main/java/com/guwan/backend/jpaTest/{ => domain}/Project.java (91%) delete mode 100644 src/main/java/com/guwan/backend/jpaTest/mapper/QueryResultMapper.java create mode 100644 src/main/java/com/guwan/backend/util/DtoGeneratorExample.java create mode 100644 src/main/java/com/guwan/backend/util/DtoGeneratorUtil.java diff --git a/src/main/java/com/guwan/backend/MergeStrategy/LambdaUtils.java b/src/main/java/com/guwan/backend/MergeStrategy/LambdaUtils.java deleted file mode 100644 index ad63519..0000000 --- a/src/main/java/com/guwan/backend/MergeStrategy/LambdaUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.guwan.backend.MergeStrategy; - -import java.io.Serializable; -import java.lang.invoke.SerializedLambda; -import java.lang.reflect.Method; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Lambda表达式和方法引用解析工具类 - */ -public class LambdaUtils { - - /** - * 从Lambda表达式或方法引用中提取属性名 - * @param getter Lambda方法引用 - * @return 属性名 - */ - public static String getPropertyName(PropertyFunction getter) { - try { - // 1. 获取SerializedLambda - Method writeReplace = getter.getClass().getDeclaredMethod("writeReplace"); - writeReplace.setAccessible(true); - SerializedLambda serializedLambda = (SerializedLambda) writeReplace.invoke(getter); - - // 2. 从SerializedLambda获取实现方法名 - String implMethodName = serializedLambda.getImplMethodName(); - - // 3. 转换方法名为属性名 - if (implMethodName.startsWith("get") && implMethodName.length() > 3) { - String propertyName = implMethodName.substring(3); - return propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); - } else if (implMethodName.startsWith("is") && implMethodName.length() > 2) { - String propertyName = implMethodName.substring(2); - return propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); - } - - return implMethodName; - } catch (Exception e) { - // 降级到常规正则表达式解析 - return parsePropertyNameByRegex(getter); - } - } - - /** - * 使用正则表达式解析属性名(备选方案) - */ - private static String parsePropertyNameByRegex(Function getter) { - // 尝试从Lambda toString()解析 - String methodRef = getter.toString(); - - // 处理方法引用格式: com.example.Entity::getName - if (methodRef.contains("::")) { - Pattern pattern = Pattern.compile("::get(\\w+)|::is(\\w+)"); - Matcher matcher = pattern.matcher(methodRef); - if (matcher.find()) { - String fieldName = matcher.group(1) != null ? matcher.group(1) : matcher.group(2); - return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); - } - - // 直接从方法名截取 - String methodName = methodRef.substring(methodRef.lastIndexOf("::") + 2); - return extractFieldNameFromMethod(methodName); - } - // 处理Lambda表达式格式: (Entity e) -> e.getName() 或 e -> e.getName() - else if (methodRef.contains("->")) { - Pattern pattern = Pattern.compile("->\\s*\\w+\\.get(\\w+)\\(\\)|->\\s*\\w+\\.is(\\w+)\\(\\)"); - Matcher matcher = pattern.matcher(methodRef); - if (matcher.find()) { - String fieldName = matcher.group(1) != null ? matcher.group(1) : matcher.group(2); - return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); - } - } - - // 处理其他情况 - 也许是已经是字段名 - return methodRef; - } - - /** - * 从方法名中提取字段名 - */ - private static String extractFieldNameFromMethod(String methodName) { - if (methodName.startsWith("get") && methodName.length() > 3) { - // getName -> name (首字母小写) - String fieldName = methodName.substring(3); - return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); - } else if (methodName.startsWith("is") && methodName.length() > 2) { - // isActive -> active (首字母小写) - String fieldName = methodName.substring(2); - return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); - } - return methodName; - } - - /** - * 可序列化的函数接口 - 用于支持方法引用解析 - */ - @FunctionalInterface - public interface PropertyFunction extends Function, Serializable { - } -} \ No newline at end of file diff --git a/src/main/java/com/guwan/backend/MergeStrategy/JoinBuilder.java b/src/main/java/com/guwan/backend/builder/JoinBuilder.java similarity index 60% rename from src/main/java/com/guwan/backend/MergeStrategy/JoinBuilder.java rename to src/main/java/com/guwan/backend/builder/JoinBuilder.java index f7e2ee9..f122d0e 100644 --- a/src/main/java/com/guwan/backend/MergeStrategy/JoinBuilder.java +++ b/src/main/java/com/guwan/backend/builder/JoinBuilder.java @@ -1,16 +1,11 @@ -package com.guwan.backend.MergeStrategy; +package com.guwan.backend.builder; import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.*; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.query.QueryUtils; import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; -import com.guwan.backend.MergeStrategy.LambdaUtils.PropertyFunction; /** * 自定义连表查询构建器 @@ -42,19 +37,6 @@ public class JoinBuilder { return this; } - /** - * 添加连接表(使用增强的方法引用) - * @param joinClass 要连接的表实体类 - * @param sourceFieldGetter 主表外键字段的getter方法引用 - * @param targetFieldGetter 连接表目标字段的getter方法引用 - */ - public JoinBuilder join(Class joinClass, - PropertyFunction sourceFieldGetter, - PropertyFunction targetFieldGetter) { - String sourceField = LambdaUtils.getPropertyName(sourceFieldGetter); - String targetField = LambdaUtils.getPropertyName(targetFieldGetter); - return join(joinClass, sourceField, targetField); - } /** * 添加等值条件 @@ -70,64 +52,6 @@ public class JoinBuilder { return this; } - /** - * 添加等值条件(使用增强的方法引用) - * @param entityClass 实体类 - * @param fieldGetter 字段的getter方法引用 - * @param value 字段值 - */ - public JoinBuilder equal(Class entityClass, PropertyFunction fieldGetter, V value) { - String fieldName = LambdaUtils.getPropertyName(fieldGetter); - return equal(entityClass, fieldName, value); - } - - /** - * 选择返回的字段 - * @param selectedFields 每个实体类需要返回的字段映射 - */ - public JoinBuilder selectFields(Map, String[]> selectedFields) { - this.selectedFields = selectedFields; - return this; - } - - /** - * 选择返回的字段(使用增强的方法引用) - * @param fieldGetters 方法引用列表 - */ - @SafeVarargs - public final JoinBuilder select(Class entityClass, PropertyFunction... fieldGetters) { - if (selectedFields == null) { - selectedFields = new HashMap<>(); - } - - String[] fieldNames = Arrays.stream(fieldGetters) - .map(LambdaUtils::getPropertyName) - .toArray(String[]::new); - - selectedFields.put(entityClass, fieldNames); - return this; - } - - /** - * 添加一个具有别名的字段选择(使用增强的方法引用) - * @param alias 字段别名 - * @param entityClass 实体类 - * @param fieldGetter 字段的getter方法引用 - */ - public JoinBuilder selectAs(String alias, Class entityClass, PropertyFunction fieldGetter) { - String fieldName = LambdaUtils.getPropertyName(fieldGetter); - - // 存储字段信息,稍后在configureSelections处理 - if (selectedFields == null) { - selectedFields = new HashMap<>(); - } - if (!selectedFields.containsKey(entityClass)) { - selectedFields.put(entityClass, new String[0]); - } - namedSelections.put(alias, new SelectionInfo(entityClass, fieldName)); - - return this; - } /** * 添加一个具有别名的字段选择(字符串版本) @@ -147,50 +71,75 @@ public class JoinBuilder { return this; } - - /** - * 设置实体间字段映射关系的别名,以便对应DTO字段 - * @param dtoClass DTO类 - * @param mappings 字段映射 - */ - @SafeVarargs - public final JoinBuilder selectDto(Class dtoClass, FieldMapping... mappings) { - for (FieldMapping mapping : mappings) { - String dtoFieldName = mapping.getDtoFieldName(); - String entityFieldName = mapping.getEntityFieldName(); - Class entityClass = mapping.getEntityClass(); - - // 存储字段信息,稍后在configureSelections处理 - if (selectedFields == null) { - selectedFields = new HashMap<>(); - } - if (!selectedFields.containsKey(entityClass)) { - selectedFields.put(entityClass, new String[0]); - } - namedSelections.put(dtoFieldName, new SelectionInfo(entityClass, entityFieldName)); + + + + public long count(EntityManager entityManager) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class); + Root root = countQuery.from(rootClass); + + // 创建连接关系 + Map, From> fromMap = createJoins(root, countQuery); + + // 应用条件,包括表之间的连接条件和额外查询条件 + List predicates = applyAllConditions(root, fromMap, criteriaBuilder); + + // 添加条件到查询 + if (!predicates.isEmpty()) { + countQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))); } - return this; + + // 设置count查询 + countQuery.select(criteriaBuilder.count(root)); + + // 执行查询并返回结果 + return entityManager.createQuery(countQuery).getSingleResult(); } - /** - * 构建规范查询 - * @return Specification 查询规范 - */ - public Specification build() { - return (root, query, criteriaBuilder) -> { - // 创建连接关系 - Map, From> joinMap = createJoins(root, query); - - // 应用连表条件和其他条件 - List predicates = applyAllConditions(root, joinMap, criteriaBuilder); - - // 设置查询结果投影 - configureSelections(root, joinMap, query); - - return criteriaBuilder.and(predicates.toArray(new Predicate[0])); - }; + public List executeAndMapWithPaging(EntityManager entityManager, + Class dtoClass, + int page, + int size) { + List results = executeWithPaging(entityManager, page, size); + return mapToDto(results, dtoClass); } - + + + public List executeWithPaging(EntityManager entityManager, int page, int size) { + // 创建CriteriaBuilder + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + // 创建CriteriaQuery + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Object[].class); + + // 设置根实体 + Root root = criteriaQuery.from(rootClass); + + // 创建连接关系 + Map, From> fromMap = createJoins(root, criteriaQuery); + + // 应用所有条件 + List predicates = applyAllConditions(root, fromMap, criteriaBuilder); + + // 添加条件到查询 + if (!predicates.isEmpty()) { + criteriaQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))); + } + + // 设置查询结果投影 + configureSelections(root, fromMap, criteriaQuery); + + // 创建查询并设置分页 + jakarta.persistence.Query query = entityManager.createQuery(criteriaQuery); + query.setFirstResult(page * size); + query.setMaxResults(size); + + // 执行查询并返回结果 + return query.getResultList(); + } + + /** * 执行查询并返回结果 * @param entityManager EntityManager实例 @@ -274,18 +223,7 @@ public class JoinBuilder { return predicates; } - - /** - * 执行查询并直接映射到DTO对象 - * @param entityManager EntityManager实例 - * @param dtoClass DTO类 - * @param DTO类型 - * @return DTO对象列表 - */ - public List executeAndMap(EntityManager entityManager, Class dtoClass) { - List results = execute(entityManager); - return mapToDto(results, dtoClass); - } + /** * 将查询结果映射到DTO对象 @@ -384,54 +322,7 @@ public class JoinBuilder { throw new UnsupportedOperationException("Unsupported operator: " + condition.operator); } } - - /** - * 字段映射定义,用于DTO映射 - */ - public static class FieldMapping { - private final String dtoFieldName; - private final String entityFieldName; - private final Class entityClass; - - private FieldMapping(String dtoFieldName, String entityFieldName, Class entityClass) { - this.dtoFieldName = dtoFieldName; - this.entityFieldName = entityFieldName; - this.entityClass = entityClass; - } - - public static FieldMapping of(PropertyFunction dtoFieldGetter, PropertyFunction entityFieldGetter) { - String dtoFieldName = LambdaUtils.getPropertyName(dtoFieldGetter); - String entityFieldName = LambdaUtils.getPropertyName(entityFieldGetter); - - // 通过反射获取entityClass - Class entityClass = null; - try { - // 尝试从方法引用中提取类信息 - Method writeReplace = entityFieldGetter.getClass().getDeclaredMethod("writeReplace"); - writeReplace.setAccessible(true); - Object serializedLambda = writeReplace.invoke(entityFieldGetter); - String implClass = (String) serializedLambda.getClass().getMethod("getImplClass").invoke(serializedLambda); - implClass = implClass.replace('/', '.'); - entityClass = (Class) Class.forName(implClass); - } catch (Exception e) { - // 忽略异常,entityClass将在运行时确定 - } - - return new FieldMapping<>(dtoFieldName, entityFieldName, entityClass); - } - - public String getDtoFieldName() { - return dtoFieldName; - } - - public String getEntityFieldName() { - return entityFieldName; - } - - public Class getEntityClass() { - return entityClass; - } - } + /** * 连接信息 diff --git a/src/main/java/com/guwan/backend/jpaTest/EmployeeController.java b/src/main/java/com/guwan/backend/jpaTest/EmployeeController.java index a3994c9..24e4efe 100644 --- a/src/main/java/com/guwan/backend/jpaTest/EmployeeController.java +++ b/src/main/java/com/guwan/backend/jpaTest/EmployeeController.java @@ -1,18 +1,16 @@ package com.guwan.backend.jpaTest; +import com.guwan.backend.jpaTest.domain.EmployeeDTO; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.sql.ResultSet; -import java.util.List; - @RestController @RequestMapping("/api/employees") public class EmployeeController { @@ -35,23 +33,12 @@ public class EmployeeController { * @return 员工DTO列表 */ @GetMapping("/details") - public List getEmployeeDetails( + public Page getEmployeeDetails( @RequestParam(required = false) String departmentName, @RequestParam(required = false, defaultValue = "false") boolean projectDeleted) { - return employeeService.getEmployeeDetails(departmentName, projectDeleted); + return employeeService.getEmployeeDetails(departmentName, projectDeleted, 0, 2); } - /** - * 根据条件查询员工信息 - * - * @param employeeName 员工名称过滤条件,可选 - * @param departmentName 部门名称过滤条件,可选 - * @return 员工DTO列表 - */ - @GetMapping("/search") - public List searchEmployees( - @RequestParam(required = false) String employeeName, - @RequestParam(required = false) String departmentName) { - return employeeService.findEmployees(employeeName, departmentName); - } + + } \ No newline at end of file diff --git a/src/main/java/com/guwan/backend/jpaTest/EmployeeRepository.java b/src/main/java/com/guwan/backend/jpaTest/EmployeeRepository.java index 3662baa..436e522 100644 --- a/src/main/java/com/guwan/backend/jpaTest/EmployeeRepository.java +++ b/src/main/java/com/guwan/backend/jpaTest/EmployeeRepository.java @@ -1,5 +1,6 @@ package com.guwan.backend.jpaTest; +import com.guwan.backend.jpaTest.domain.Employee; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/guwan/backend/jpaTest/EmployeeService.java b/src/main/java/com/guwan/backend/jpaTest/EmployeeService.java index 19a4902..001ee83 100644 --- a/src/main/java/com/guwan/backend/jpaTest/EmployeeService.java +++ b/src/main/java/com/guwan/backend/jpaTest/EmployeeService.java @@ -1,11 +1,16 @@ package com.guwan.backend.jpaTest; -import com.guwan.backend.MergeStrategy.JoinBuilder; -import com.guwan.backend.MergeStrategy.JoinBuilder.FieldMapping; -import com.guwan.backend.MergeStrategy.LambdaUtils.PropertyFunction; +import com.guwan.backend.builder.JoinBuilder; +import com.guwan.backend.jpaTest.domain.Department; +import com.guwan.backend.jpaTest.domain.Employee; +import com.guwan.backend.jpaTest.domain.EmployeeDTO; +import com.guwan.backend.jpaTest.domain.Project; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import java.util.List; @@ -27,7 +32,8 @@ public class EmployeeService { * @param projectDeleted 项目是否已删除的过滤条件 * @return 员工DTO列表 */ - public List getEmployeeDetails(String departmentName, boolean projectDeleted) { + public Page getEmployeeDetails(String departmentName, boolean projectDeleted, + int page, int size) { // 创建查询构建器,从Employee实体开始 JoinBuilder builder = JoinBuilder.from(Employee.class); @@ -47,77 +53,19 @@ public class EmployeeService { builder.selectAs("departmentName", Department.class, "name"); builder.selectAs("projectName", Project.class, "name"); - // 直接执行查询并映射到DTO - return builder.executeAndMap(entityManager, EmployeeDTO.class); + // 先获取总记录数 + long total = builder.count(entityManager); + + // 执行分页查询并映射到DTO + List content = builder.executeAndMapWithPaging( + entityManager, + EmployeeDTO.class, + page, + size + ); + + // 返回分页结果 + return new PageImpl<>(content, PageRequest.of(page, size), total); } - - /** - * 使用自定义条件查询员工信息 - * 使用新的方法引用方式 - * - * @param employeeName 员工名称过滤条件,可选 - * @param departmentName 部门名称过滤条件,可选 - * @return 员工DTO列表 - */ - public List findEmployees(String employeeName, String departmentName) { - JoinBuilder builder = JoinBuilder.from(Employee.class); - - // 尝试使用增强的方法引用 - try { - // 添加关联,使用增强的方法引用 - builder.join(Department.class, - (PropertyFunction) Employee::getDepartmentId, - (PropertyFunction) Department::getId); - builder.join(Project.class, - (PropertyFunction) Employee::getProjectId, - (PropertyFunction) Project::getId); - - // 添加查询条件,使用增强的方法引用 - if (employeeName != null && !employeeName.isEmpty()) { - builder.equal(Employee.class, - (PropertyFunction) Employee::getName, - employeeName); - } - - if (departmentName != null && !departmentName.isEmpty()) { - builder.equal(Department.class, - (PropertyFunction) Department::getName, - departmentName); - } - - // 使用selectAs配合增强的方法引用 - builder.selectAs("employeeId", Employee.class, - (PropertyFunction) Employee::getId); - builder.selectAs("employeeName", Employee.class, - (PropertyFunction) Employee::getName); - builder.selectAs("departmentName", Department.class, - (PropertyFunction) Department::getName); - builder.selectAs("projectName", Project.class, - (PropertyFunction) Project::getName); - } - catch (Exception e) { - /* // 如果增强方法引用失败,回退到字符串方式 - builder = JoinBuilder.from(Employee.class); - // 使用字符串作为回退方案 - builder.join(Department.class, "departmentId", "id"); - builder.join(Project.class, "projectId", "id"); - - if (employeeName != null && !employeeName.isEmpty()) { - builder.equal(Employee.class, "name", employeeName); - } - - if (departmentName != null && !departmentName.isEmpty()) { - builder.equal(Department.class, "name", departmentName); - } - - builder.selectAs("employeeId", Employee.class, "id"); - builder.selectAs("employeeName", Employee.class, "name"); - builder.selectAs("departmentName", Department.class, "name"); - builder.selectAs("projectName", Project.class, "name");*/ - } - - // 直接执行查询并映射到DTO - return builder.executeAndMap(entityManager, EmployeeDTO.class); - } } \ No newline at end of file diff --git a/src/main/java/com/guwan/backend/jpaTest/Department.java b/src/main/java/com/guwan/backend/jpaTest/domain/Department.java similarity index 90% rename from src/main/java/com/guwan/backend/jpaTest/Department.java rename to src/main/java/com/guwan/backend/jpaTest/domain/Department.java index acd634b..febddde 100644 --- a/src/main/java/com/guwan/backend/jpaTest/Department.java +++ b/src/main/java/com/guwan/backend/jpaTest/domain/Department.java @@ -1,4 +1,4 @@ -package com.guwan.backend.jpaTest; +package com.guwan.backend.jpaTest.domain; import jakarta.persistence.Entity; import jakarta.persistence.Id; diff --git a/src/main/java/com/guwan/backend/jpaTest/Employee.java b/src/main/java/com/guwan/backend/jpaTest/domain/Employee.java similarity index 93% rename from src/main/java/com/guwan/backend/jpaTest/Employee.java rename to src/main/java/com/guwan/backend/jpaTest/domain/Employee.java index bc7a501..721bfe7 100644 --- a/src/main/java/com/guwan/backend/jpaTest/Employee.java +++ b/src/main/java/com/guwan/backend/jpaTest/domain/Employee.java @@ -1,4 +1,4 @@ -package com.guwan.backend.jpaTest; +package com.guwan.backend.jpaTest.domain; import jakarta.persistence.Entity; import jakarta.persistence.Id; diff --git a/src/main/java/com/guwan/backend/jpaTest/EmployeeDTO.java b/src/main/java/com/guwan/backend/jpaTest/domain/EmployeeDTO.java similarity index 95% rename from src/main/java/com/guwan/backend/jpaTest/EmployeeDTO.java rename to src/main/java/com/guwan/backend/jpaTest/domain/EmployeeDTO.java index 50238b0..2320d9a 100644 --- a/src/main/java/com/guwan/backend/jpaTest/EmployeeDTO.java +++ b/src/main/java/com/guwan/backend/jpaTest/domain/EmployeeDTO.java @@ -1,4 +1,4 @@ -package com.guwan.backend.jpaTest; +package com.guwan.backend.jpaTest.domain; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/com/guwan/backend/jpaTest/Project.java b/src/main/java/com/guwan/backend/jpaTest/domain/Project.java similarity index 91% rename from src/main/java/com/guwan/backend/jpaTest/Project.java rename to src/main/java/com/guwan/backend/jpaTest/domain/Project.java index ac9ff5e..a98f274 100644 --- a/src/main/java/com/guwan/backend/jpaTest/Project.java +++ b/src/main/java/com/guwan/backend/jpaTest/domain/Project.java @@ -1,4 +1,4 @@ -package com.guwan.backend.jpaTest; +package com.guwan.backend.jpaTest.domain; import jakarta.persistence.Entity; import jakarta.persistence.Id; diff --git a/src/main/java/com/guwan/backend/jpaTest/mapper/QueryResultMapper.java b/src/main/java/com/guwan/backend/jpaTest/mapper/QueryResultMapper.java deleted file mode 100644 index 6c9deaa..0000000 --- a/src/main/java/com/guwan/backend/jpaTest/mapper/QueryResultMapper.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.guwan.backend.jpaTest.mapper; - -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * 查询结果映射工具类 - * 用于将原始查询结果转换为更有意义的对象 - */ -public class QueryResultMapper { - - /** - * 将Object[]结果列表映射为指定类型的对象列表 - * @param results 查询结果 - * @param mapper 映射函数 - * @return 映射后的对象列表 - */ - public static List mapToList(List results, Function mapper) { - return results.stream() - .map(row -> mapper.apply(new ResultRow(row))) - .collect(Collectors.toList()); - } - - /** - * 将Object[]结果列表使用命名方式映射为指定类型的对象列表 - * @param results 查询结果 - * @param columnMap 列名到索引的映射 - * @param mapper 映射函数 - * @return 映射后的对象列表 - */ - public static List mapToListWithNames(List results, - Map columnMap, - Function mapper) { - return results.stream() - .map(row -> mapper.apply(new NamedResultRow(row, columnMap))) - .collect(Collectors.toList()); - } - - /** - * 结果行封装,提供类型安全的访问方法 - */ - public static class ResultRow { - private final Object[] row; - - public ResultRow(Object[] row) { - this.row = row; - } - - public Long getLong(int index) { - Object value = getValue(index); - if (value == null) return null; - if (value instanceof Long) return (Long) value; - if (value instanceof Number) return ((Number) value).longValue(); - return Long.valueOf(value.toString()); - } - - public Integer getInteger(int index) { - Object value = getValue(index); - if (value == null) return null; - if (value instanceof Integer) return (Integer) value; - if (value instanceof Number) return ((Number) value).intValue(); - return Integer.valueOf(value.toString()); - } - - public String getString(int index) { - Object value = getValue(index); - return value == null ? null : value.toString(); - } - - public Boolean getBoolean(int index) { - Object value = getValue(index); - if (value == null) return null; - if (value instanceof Boolean) return (Boolean) value; - if (value instanceof Number) return ((Number) value).intValue() != 0; - return Boolean.valueOf(value.toString()); - } - - public Object getValue(int index) { - if (index < 0 || index >= row.length) { - throw new IndexOutOfBoundsException("索引超出范围: " + index); - } - return row[index]; - } - } - - /** - * 命名结果行封装,通过列名访问数据 - */ - public static class NamedResultRow { - private final Object[] row; - private final Map columnMap; - - public NamedResultRow(Object[] row, Map columnMap) { - this.row = row; - this.columnMap = columnMap; - } - - public Long getLong(String columnName) { - Object value = getValue(columnName); - if (value == null) return null; - if (value instanceof Long) return (Long) value; - if (value instanceof Number) return ((Number) value).longValue(); - return Long.valueOf(value.toString()); - } - - public Integer getInteger(String columnName) { - Object value = getValue(columnName); - if (value == null) return null; - if (value instanceof Integer) return (Integer) value; - if (value instanceof Number) return ((Number) value).intValue(); - return Integer.valueOf(value.toString()); - } - - public String getString(String columnName) { - Object value = getValue(columnName); - return value == null ? null : value.toString(); - } - - public Boolean getBoolean(String columnName) { - Object value = getValue(columnName); - if (value == null) return null; - if (value instanceof Boolean) return (Boolean) value; - if (value instanceof Number) return ((Number) value).intValue() != 0; - return Boolean.valueOf(value.toString()); - } - - public Object getValue(String columnName) { - Integer index = columnMap.get(columnName); - if (index == null) { - throw new IllegalArgumentException("列名不存在: " + columnName); - } - if (index < 0 || index >= row.length) { - throw new IndexOutOfBoundsException("索引超出范围: " + index); - } - return row[index]; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/guwan/backend/util/DtoGeneratorExample.java b/src/main/java/com/guwan/backend/util/DtoGeneratorExample.java new file mode 100644 index 0000000..ef13a0e --- /dev/null +++ b/src/main/java/com/guwan/backend/util/DtoGeneratorExample.java @@ -0,0 +1,14 @@ +package com.guwan.backend.util; + +import com.guwan.backend.jpaTest.domain.EmployeeDTO; + +// 示例用法 +public class DtoGeneratorExample { + public static void main(String[] args) { + // 为EmployeeDTO生成构造函数 + String constructor = DtoGeneratorUtil.generateDtoConstructor(EmployeeDTO.class); + System.out.println(constructor); + + + } +} \ No newline at end of file diff --git a/src/main/java/com/guwan/backend/util/DtoGeneratorUtil.java b/src/main/java/com/guwan/backend/util/DtoGeneratorUtil.java new file mode 100644 index 0000000..8e2e69c --- /dev/null +++ b/src/main/java/com/guwan/backend/util/DtoGeneratorUtil.java @@ -0,0 +1,57 @@ +package com.guwan.backend.util; + +import java.lang.reflect.Field; + +public class DtoGeneratorUtil { + + public static String generateDtoConstructor(Class dtoClass) { + StringBuilder sb = new StringBuilder(); + Field[] fields = dtoClass.getDeclaredFields(); + + // 构造函数参数 + sb.append("public ").append(dtoClass.getSimpleName()) + .append("("); + for (int i = 0; i < fields.length; i++) { + if (i > 0) sb.append(", "); + sb.append("Object ").append(fields[i].getName()); + } + sb.append(") {\n"); + + // 构造函数体 + for (Field field : fields) { + String fieldName = field.getName(); + String conversion = getConversion(field.getType(), fieldName); + sb.append(" this.").append(fieldName) + .append(" = ").append(fieldName).append(" != null ? ") + .append(conversion).append(" : null;\n"); + } + + sb.append("}"); + return sb.toString(); + } + + private static String getConversion(Class type, String fieldName) { + if (type == String.class) { + return "String.valueOf(" + fieldName + ")"; + } else if (type == Long.class || type == long.class) { + return "Long.valueOf(" + fieldName + ".toString())"; + } else if (type == Integer.class || type == int.class) { + return "Integer.valueOf(" + fieldName + ".toString())"; + } else if (type == Double.class || type == double.class) { + return "Double.valueOf(" + fieldName + ".toString())"; + } else if (type == Boolean.class || type == boolean.class) { + return "Boolean.valueOf(" + fieldName + ".toString())"; + } else if (type == java.util.Date.class) { + return "(" + fieldName + " instanceof java.util.Date) ? (" + + "java.util.Date) " + fieldName + " : new java.text.SimpleDateFormat(\"yyyy-MM-dd\").parse(" + + fieldName + ".toString())"; + } else if (type == java.time.LocalDate.class) { + return "java.time.LocalDate.parse(" + fieldName + ".toString())"; + } else if (type == java.time.LocalDateTime.class) { + return "java.time.LocalDateTime.parse(" + fieldName + ".toString())"; + } else { + // 对于其它复杂类型,可能需要更特殊的处理 + return "(" + type.getSimpleName() + ") " + fieldName; + } + } +} \ No newline at end of file