This commit is contained in:
2024-04-19 17:53:49 +08:00
parent eb43da8160
commit 79d18cc245
10 changed files with 240 additions and 94 deletions

View File

@@ -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<String, String> underscoreToCamelCase =
(String name) -> CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
public static Function<Object, String> 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<Map<String, Object>> convertTuplesToMap(List<Tuple> 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<Object, String>) ReflectUtils::getId).apply(x), maps, "id", conversionService);
}
@@ -109,7 +82,6 @@ public class JpaUtils {
Map<ID, Map> mapMap =
StreamSupport.stream(maps.spliterator(), false)
.collect(Collectors.toMap(e -> (ID) e.get(mapKey), Function.identity()));
Map<Class, Map<String, Field>> 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()));
}
}
}

View File

@@ -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<Class, List<Field>> fieldCache =
CacheBuilder.newBuilder()
.maximumSize(10000)
.build(
new CacheLoader<Class, List<Field>>() {
@Override
public List<Field> load(Class key) throws Exception {
return FieldUtils.getAllFieldsList(key);
}
});
private static final Cache<Tuple2<Class, String>, Optional<Field>> 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<Field> 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<String> idList(Object dtos) {
if (dtos instanceof Iterable<?>) {
return ((List<?>) dtos).stream().map(ReflectUtils::getId).toList();
}else {
return List.of(ReflectUtils.getId(dtos));
}
}
}

View File

@@ -130,6 +130,26 @@ public class TreeUtils {
}
}
public static <T> List<T> treeToList(Iterable<T> src) {
return treeToList(src, n -> (Iterable<T>) ReflectUtils.invokeMethod(n, "getChildren"));
}
public static <T> List<T> treeToList(Iterable<T> src, Function<T, Iterable<T>> getChildren) {
return treeToList(src, getChildren, ReflectUtils::getId);
}
public static <T> List<T> treeToList(Iterable<T> src, Function<T, Iterable<T>> getChildren, Function<T, Object> hashFn) {
List<T> ans = new ArrayList<>();
dfsList(
src,
getChildren,
x -> {
ans.add(x.current);
},
hashFn);
return ans;
}
@Data
public static class DFSCtx<T>{

View File

@@ -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<DepartmentEntity, DepartmentReposito
private List<DepartmentTreeDto> addEmpIds(List<DepartmentTreeDto> collect) {
List<Map> 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<DepartmentDto> list(CommonQuery query) {

View File

@@ -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<String> 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<String> childrenDeviceIds;
@Type(ListArrayType.class)
@Formula("(select array_agg(e.id) from t_device e where e.category_id = id)")
private List<String> selfDeviceIds;
@ManyToOne private DeviceCategoryEntity parent;

View File

@@ -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<DeviceCategoryEntity> {}
public interface DeviceCategoryRepository extends BaseRepository<DeviceCategoryEntity> {
@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<Map> deviceIds(@Param("ids") List<String> ids);
}

View File

@@ -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<DeviceCategoryTreeDto> collect = roots.stream()
.map(de -> this.mapper.toTreeDto(de))
.collect(Collectors.toList());
return addDeviceIds(
collect);
} else {
Page<DeviceCategoryEntity> page =
repository.findAll(
@@ -104,11 +112,11 @@ public class DeviceCategoryService
true);
List<DeviceCategoryTreeDto> 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<DeviceCategoryTreeDto> addDeviceIds(List<DeviceCategoryTreeDto> collect) {
var dtos = TreeUtils.treeToList(collect);
var maps = repository.deviceIds(ReflectUtils.idList(dtos));
JpaUtils.mergeMapToPojo (dtos, maps, conversionService);
return collect;
}
public List<DeviceCategoryTreeDto> getTreeByIds(IdRequest request) {
if (request.getIds().isEmpty()) {
return new ArrayList<>();

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}