diff --git a/src/main/java/cn/lihongjie/coal/common/JpaUtils.java b/src/main/java/cn/lihongjie/coal/common/JpaUtils.java index b3da132d..10e02e31 100644 --- a/src/main/java/cn/lihongjie/coal/common/JpaUtils.java +++ b/src/main/java/cn/lihongjie/coal/common/JpaUtils.java @@ -1,7 +1,5 @@ package cn.lihongjie.coal.common; -import cn.lihongjie.coal.base.dto.BaseDto; -import cn.lihongjie.coal.base.entity.BaseEntity; import com.google.common.base.CaseFormat; @@ -13,8 +11,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.reflect.FieldUtils; -import org.apache.poi.ss.formula.functions.T; import org.springframework.core.convert.ConversionService; import java.lang.reflect.Field; @@ -29,29 +25,6 @@ public class JpaUtils { public static Function underscoreToCamelCase = (String name) -> CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name); - public static Function idGetter = (Object obj) -> { - if (obj == null) { - return null; - } - if (obj instanceof Map) { - return ((Map) obj).get("id").toString(); - } - - if (obj instanceof BaseEntity){ - return ((BaseEntity) obj).getId(); - } - if (obj instanceof BaseDto){ - return ((BaseDto) obj).getId(); - } - - try{ - return FieldUtils.readField(obj, "id", true).toString(); - }catch (Exception e){ - return null; - } - - }; - public static List> convertTuplesToMap(List tuples) { return convertTuplesToMap(tuples, Function.identity(), Function.identity()); @@ -81,7 +54,7 @@ public class JpaUtils { ConversionService conversionService) { - mergeMapToPojo(pojos, x -> idGetter.apply(x), maps, "id", conversionService); + mergeMapToPojo(pojos, x -> ((Function) ReflectUtils::getId).apply(x), maps, "id", conversionService); } @@ -109,7 +82,6 @@ public class JpaUtils { Map mapMap = StreamSupport.stream(maps.spliterator(), false) .collect(Collectors.toMap(e -> (ID) e.get(mapKey), Function.identity())); - Map> fieldMapCache = new HashMap<>(); for (ID id : mapMap.keySet()) { @@ -119,12 +91,6 @@ public class JpaUtils { continue; } - var fields = - fieldMapCache.computeIfAbsent( - pojo.getClass(), - cls -> - FieldUtils.getAllFieldsList(cls).stream() - .collect(Collectors.toMap(e -> e.getName(), e -> e))); Map map = mapMap.get(id); @@ -136,12 +102,12 @@ public class JpaUtils { String fieldName = key.toString(); Object value = map.get(key); - if (!fields.containsKey(fieldName)) { + if (!ReflectUtils.hasField(pojo.getClass(), fieldName)) { fieldName = underscoreToCamelCase.apply(fieldName); } - if (!fields.containsKey(fieldName)) { + if (!ReflectUtils.hasField(pojo.getClass(), fieldName)) { log.info( "field {}/{} not found in class {}", @@ -151,10 +117,11 @@ public class JpaUtils { continue; } - Field field = fields.get(fieldName); + Field field = ReflectUtils.getField(pojo.getClass(), fieldName).get(); - FieldUtils.writeField( - field, pojo, conversionService.convert(value, field.getType()), true); + ReflectUtils.writeField(pojo, fieldName, conversionService.convert(value, field.getType())); + + } } } diff --git a/src/main/java/cn/lihongjie/coal/common/ReflectUtils.java b/src/main/java/cn/lihongjie/coal/common/ReflectUtils.java index 44cefce4..5c387347 100644 --- a/src/main/java/cn/lihongjie/coal/common/ReflectUtils.java +++ b/src/main/java/cn/lihongjie/coal/common/ReflectUtils.java @@ -1,13 +1,157 @@ package cn.lihongjie.coal.common; -import java.lang.reflect.Field; +import cn.lihongjie.coal.base.dto.BaseDto; +import cn.lihongjie.coal.base.entity.BaseEntity; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; + +import io.vavr.Tuple2; + +import lombok.SneakyThrows; import lombok.experimental.UtilityClass; + +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.commons.lang3.reflect.MethodUtils; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; +import java.util.Optional; + @UtilityClass public class ReflectUtils { + private static final Cache> fieldCache = + CacheBuilder.newBuilder() + .maximumSize(10000) + .build( + new CacheLoader>() { + @Override + public List load(Class key) throws Exception { + return FieldUtils.getAllFieldsList(key); + } + }); + private static final Cache, Optional> getFieldCache = + CacheBuilder.newBuilder().maximumSize(10000).build(); + + public static String getId(Object o) { + + if (o == null) { + return null; + } + + if (o instanceof BaseEntity) { + return ((BaseEntity) o).getId(); + } + + if (o instanceof BaseDto) { + + return ((BaseDto) o).getId(); + } + + if (o instanceof String) { + return (String) o; + } + if (o instanceof Map) { + return (String) ((Map) o).get("id"); + } + + if (hasField(o.getClass(), "id")) { + return (String) getFieldValue(o, "id"); + } + + try { + + return (String) invokeMethod(o, "getId"); + } catch (Exception e) { + // ignore + } + + throw new RuntimeException("无法获取id"); + } + + public static boolean hasField(Class cls, String fieldName) { + + return getField(cls, fieldName).isPresent(); + } + + @SneakyThrows + public static Optional getField(Class cls, String fieldName) { + + if (cls == null) { + return Optional.empty(); + } + + if (StringUtils.isEmpty(fieldName)) { + return Optional.empty(); + } + + return getFieldCache.get( + new Tuple2<>(cls, fieldName), + () -> { + return fieldCache.get(cls, () -> FieldUtils.getAllFieldsList(cls)).stream() + .filter(x -> x.getName().equals(fieldName)) + .findFirst(); + }); + } + + @SneakyThrows + public static Object invokeMethod(Object object, String methodName) { + return MethodUtils.invokeMethod(object, methodName); + } + + @SneakyThrows + public static Object invokeMethod(Object object, String methodName, Object... args) { + + return MethodUtils.invokeMethod(object, methodName, args); + } + + @SneakyThrows + public static Object readField(Object o, String field) { + return readField(o, field, true); + } + + @SneakyThrows + public static Object readField(Object o, String field, boolean forceAccess) { + if (ObjectUtils.isEmpty(o) || StringUtils.isEmpty(field)) { + return null; + } + + return getField(o.getClass(), field) + .map(x -> getReadField(x, o, forceAccess)) + .orElse(null); + + } + + @SneakyThrows + public static Object getReadField(Field x, Object o, boolean forceAccess){ + return FieldUtils.readField(x, o, forceAccess); + } + + @SneakyThrows + public static void writeField(Object o, String field, Object val) { + writeField(o, field, val, true); + } + + @SneakyThrows + public static void writeField(Object o, String field, Object val, boolean forceAccess) { + if (ObjectUtils.isEmpty(o) || StringUtils.isEmpty(field)) { + return; + } + + getField(o.getClass(), field) + .ifPresent(x -> writeField(x, o, val, forceAccess)); + } + @SneakyThrows + public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess){ + FieldUtils.writeField(field, target, value, forceAccess); + } + public static Object getFieldValue(Object object, String fieldName) { if (object == null) { @@ -25,4 +169,16 @@ public class ReflectUtils { } return null; } + + public static List idList(Object dtos) { + + + + if (dtos instanceof Iterable) { + + return ((List) dtos).stream().map(ReflectUtils::getId).toList(); + }else { + return List.of(ReflectUtils.getId(dtos)); + } + } } diff --git a/src/main/java/cn/lihongjie/coal/common/TreeUtils.java b/src/main/java/cn/lihongjie/coal/common/TreeUtils.java index 6f161d8a..0805d694 100644 --- a/src/main/java/cn/lihongjie/coal/common/TreeUtils.java +++ b/src/main/java/cn/lihongjie/coal/common/TreeUtils.java @@ -130,6 +130,26 @@ public class TreeUtils { } } + public static List treeToList(Iterable src) { + return treeToList(src, n -> (Iterable) ReflectUtils.invokeMethod(n, "getChildren")); + } + + public static List treeToList(Iterable src, Function> getChildren) { + return treeToList(src, getChildren, ReflectUtils::getId); + } + + public static List treeToList(Iterable src, Function> getChildren, Function hashFn) { + List ans = new ArrayList<>(); + dfsList( + src, + getChildren, + x -> { + ans.add(x.current); + }, + hashFn); + return ans; + } + @Data public static class DFSCtx{ diff --git a/src/main/java/cn/lihongjie/coal/department/service/DepartmentService.java b/src/main/java/cn/lihongjie/coal/department/service/DepartmentService.java index 3ebd904a..35a415b1 100644 --- a/src/main/java/cn/lihongjie/coal/department/service/DepartmentService.java +++ b/src/main/java/cn/lihongjie/coal/department/service/DepartmentService.java @@ -5,6 +5,7 @@ import cn.lihongjie.coal.base.dto.IdRequest; import cn.lihongjie.coal.base.service.BaseService; import cn.lihongjie.coal.common.Ctx; import cn.lihongjie.coal.common.JpaUtils; +import cn.lihongjie.coal.common.ReflectUtils; import cn.lihongjie.coal.common.TreeUtils; import cn.lihongjie.coal.dbFunctions.DbFunctionService; import cn.lihongjie.coal.department.dto.CreateDepartmentDto; @@ -32,7 +33,6 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -145,12 +145,15 @@ class DepartmentService extends BaseService addEmpIds(List collect) { - List maps = repository.empIds( - cn.lihongjie.coal.common.CollectionUtils.map(collect, DepartmentTreeDto::getId)); + var dtos = TreeUtils.treeToList(collect); - JpaUtils.mergeMapToPojo(collect, maps, conversionService); + var maps = repository.empIds(ReflectUtils.idList(dtos)); + + JpaUtils.mergeMapToPojo(dtos, maps, conversionService); return collect; + + } public Page list(CommonQuery query) { diff --git a/src/main/java/cn/lihongjie/coal/deviceCategory/entity/DeviceCategoryEntity.java b/src/main/java/cn/lihongjie/coal/deviceCategory/entity/DeviceCategoryEntity.java index e45bc894..9d10838e 100644 --- a/src/main/java/cn/lihongjie/coal/deviceCategory/entity/DeviceCategoryEntity.java +++ b/src/main/java/cn/lihongjie/coal/deviceCategory/entity/DeviceCategoryEntity.java @@ -2,8 +2,6 @@ package cn.lihongjie.coal.deviceCategory.entity; import cn.lihongjie.coal.base.entity.OrgCommonEntity; -import io.hypersistence.utils.hibernate.type.array.ListArrayType; - import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.ManyToOne; @@ -11,26 +9,13 @@ import jakarta.persistence.OneToMany; import lombok.Data; -import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; - import java.util.List; @Data @Entity public class DeviceCategoryEntity extends OrgCommonEntity { - @Type(ListArrayType.class) - @Formula("(select array_agg(e.id) from t_device e where e.category_id = any(self_and_children_ids('t_device_category', id, true)))") - private List allDeviceIds; - @Type(ListArrayType.class) - @Formula("(select array_agg(e.id) from t_device e where e.category_id = any(self_and_children_ids('t_device_category', id, false)))") - private List childrenDeviceIds; - - @Type(ListArrayType.class) - @Formula("(select array_agg(e.id) from t_device e where e.category_id = id)") - private List selfDeviceIds; @ManyToOne private DeviceCategoryEntity parent; diff --git a/src/main/java/cn/lihongjie/coal/deviceCategory/repository/DeviceCategoryRepository.java b/src/main/java/cn/lihongjie/coal/deviceCategory/repository/DeviceCategoryRepository.java index 8709dd26..1b0ff706 100644 --- a/src/main/java/cn/lihongjie/coal/deviceCategory/repository/DeviceCategoryRepository.java +++ b/src/main/java/cn/lihongjie/coal/deviceCategory/repository/DeviceCategoryRepository.java @@ -3,7 +3,30 @@ package cn.lihongjie.coal.deviceCategory.repository; import cn.lihongjie.coal.base.dao.BaseRepository; import cn.lihongjie.coal.deviceCategory.entity.DeviceCategoryEntity; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Map; + @Repository -public interface DeviceCategoryRepository extends BaseRepository {} +public interface DeviceCategoryRepository extends BaseRepository { + + + @Query( + value = """ + + + + select d.id as id, + (select array_agg(e.id) from t_device e where e.category_id = any(self_and_children_ids('t_device_category', d.id, true))) as all_device_ids, + (select array_agg(e.id) from t_device e where e.category_id = any(self_and_children_ids('t_device_category', d.id, false))) as children_device_ids, + (select array_agg(e.id) from t_device e where e.category_id = d.id) as self_device_ids + + from t_device_category d where d.id in :ids + +""", nativeQuery = true) + List deviceIds(@Param("ids") List ids); + +} diff --git a/src/main/java/cn/lihongjie/coal/deviceCategory/service/DeviceCategoryService.java b/src/main/java/cn/lihongjie/coal/deviceCategory/service/DeviceCategoryService.java index 93f77ded..006d058c 100644 --- a/src/main/java/cn/lihongjie/coal/deviceCategory/service/DeviceCategoryService.java +++ b/src/main/java/cn/lihongjie/coal/deviceCategory/service/DeviceCategoryService.java @@ -3,6 +3,8 @@ package cn.lihongjie.coal.deviceCategory.service; import cn.lihongjie.coal.base.dto.CommonQuery; import cn.lihongjie.coal.base.dto.IdRequest; import cn.lihongjie.coal.base.service.BaseService; +import cn.lihongjie.coal.common.JpaUtils; +import cn.lihongjie.coal.common.ReflectUtils; import cn.lihongjie.coal.common.TreeUtils; import cn.lihongjie.coal.dbFunctions.DbFunctionService; import cn.lihongjie.coal.deviceCategory.dto.CreateDeviceCategoryDto; @@ -87,7 +89,13 @@ public class DeviceCategoryService this.repository.findAll( (root, query, criteriaBuilder) -> criteriaBuilder.isNull(root.get("parent"))); - return roots.stream().map(de -> this.mapper.toTreeDto(de)).collect(Collectors.toList()); + List collect = roots.stream() + .map(de -> this.mapper.toTreeDto(de)) + .collect(Collectors.toList()); + + + return addDeviceIds( + collect); } else { Page page = repository.findAll( @@ -104,11 +112,11 @@ public class DeviceCategoryService true); List selfAndParent = - this.findAllByIds(selfAndParentIds).stream() + addDeviceIds(this.findAllByIds(selfAndParentIds).stream() .map(x -> (this.mapper.toTreeDtoExcludeChildren(x))) - .collect(Collectors.toList()); + .collect(Collectors.toList())); - return StreamSupport.stream( + return (StreamSupport.stream( TreeUtils.buildTreeFromList( selfAndParent, DeviceCategoryTreeDto::getId, @@ -122,10 +130,21 @@ public class DeviceCategoryService }) .spliterator(), false) - .collect(Collectors.toList()); + .collect(Collectors.toList())); } } + private List addDeviceIds(List collect) { + + + var dtos = TreeUtils.treeToList(collect); + + var maps = repository.deviceIds(ReflectUtils.idList(dtos)); + + JpaUtils.mergeMapToPojo (dtos, maps, conversionService); + return collect; + } + public List getTreeByIds(IdRequest request) { if (request.getIds().isEmpty()) { return new ArrayList<>(); diff --git a/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/UpdateEmpSalaryItemDto.java b/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/UpdateEmpSalaryItemDto.java index ef4cd9ec..383e00b3 100644 --- a/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/UpdateEmpSalaryItemDto.java +++ b/src/main/java/cn/lihongjie/coal/empSalaryItem/dto/UpdateEmpSalaryItemDto.java @@ -10,7 +10,6 @@ import cn.lihongjie.coal.validator.RequireName; import lombok.Data; import org.hibernate.annotations.Comment; -import org.hibernate.annotations.Formula; @Data @RequireName @@ -38,15 +37,7 @@ public class UpdateEmpSalaryItemDto extends OrgCommonDto { @Comment("工资项目录入方式") private String inputType; - @Formula( - "(select i.name\n" - + "from t_dictionary d,\n" - + " t_dictionary_item i\n" - + "where d.id = i.dictionary_id\n" - + " and d.code = 'salaryItem.inputType'\n" - + " and i.code = input_type)") - // @Comment("工资项目录入方式-名称") - private String inputTypeName; + @Comment("公式-显示") private String formulaShow; diff --git a/src/main/java/cn/lihongjie/coal/loginUserHis/dto/CreateLoginUserHisDto.java b/src/main/java/cn/lihongjie/coal/loginUserHis/dto/CreateLoginUserHisDto.java index e6508b7d..8d93c7ff 100644 --- a/src/main/java/cn/lihongjie/coal/loginUserHis/dto/CreateLoginUserHisDto.java +++ b/src/main/java/cn/lihongjie/coal/loginUserHis/dto/CreateLoginUserHisDto.java @@ -5,7 +5,6 @@ import cn.lihongjie.coal.base.dto.CommonDto; import lombok.Data; import org.hibernate.annotations.Comment; -import org.hibernate.annotations.Formula; import java.time.LocalDateTime; @@ -38,12 +37,4 @@ public class CreateLoginUserHisDto extends CommonDto { private String logoutType; - @Formula( - "(select i.name\n" - + "from t_dictionary d,\n" - + " t_dictionary_item i\n" - + "where d.id = i.dictionary_id\n" - + " and d.code = 'loginUserHis.logoutType'\n" - + " and i.code = logout_type)") - private String logoutTypeName; } diff --git a/src/main/java/cn/lihongjie/coal/loginUserHis/dto/UpdateLoginUserHisDto.java b/src/main/java/cn/lihongjie/coal/loginUserHis/dto/UpdateLoginUserHisDto.java index bd7e7198..1910818f 100644 --- a/src/main/java/cn/lihongjie/coal/loginUserHis/dto/UpdateLoginUserHisDto.java +++ b/src/main/java/cn/lihongjie/coal/loginUserHis/dto/UpdateLoginUserHisDto.java @@ -5,7 +5,6 @@ import cn.lihongjie.coal.base.dto.CommonDto; import lombok.Data; import org.hibernate.annotations.Comment; -import org.hibernate.annotations.Formula; import java.time.LocalDateTime; @@ -37,12 +36,4 @@ public class UpdateLoginUserHisDto extends CommonDto { private String logoutType; - @Formula( - "(select i.name\n" - + "from t_dictionary d,\n" - + " t_dictionary_item i\n" - + "where d.id = i.dictionary_id\n" - + " and d.code = 'loginUserHis.logoutType'\n" - + " and i.code = logout_type)") - private String logoutTypeName; }