确认
当前程序版本
3.5.9
问题描述
`package com.fengjun.finance.vo;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fengjun.finance.entity.Enterprise; import com.fengjun.finance.utils.SnowflakeIdGenerator; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.util.StringUtils;
import java.time.LocalDate; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors;
/* * @ClassName EnterpriseVO * @Description TODO * @Author ywy * @Date 2024/10/10 17:43 / @Data @Builder @AllArgsConstructor @NoArgsConstructor public class EnterpriseVO {
@JsonSerialize(using = ToStringSerializer.class)
private Long enterpriseId;
private String enterpriseName;
private String enterpriseAbbreviationName;
@JsonSerialize(using = ToStringSerializer.class)
private Long parentId;
private Byte archivingStatus;
private Byte completionStatus;
private Byte enterpriseType;
private String mnemonicCode;
private String taxpayerIdentificationNumber;
private String enterpriseProvince;
private String enterpriseCity;
private Byte businessType;
private String signatureAnnotator;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate periodWhichBelongsStart;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate periodWhichBelongsEnd;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate reportDate;
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
private String userName;
private String nickName;
private Byte userType;
/**
* 企业组
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long enterpriseGroup;
private Integer sort;
private Boolean isLowestMerge;
private List<UserVO> users;
/**
* 子节点
*/
private List<EnterpriseVO> children = new ArrayList<>();
/**
* 科目余额表导入状态,1导入了,2 没导入
*/
private Integer accountBalanceUploadStatus;
/**
* 科目余额表匹配状态1全匹配了,2 没全匹配
*/
private Integer accountBalanceMatchStatus;
/**
* tb的校验状态
*/
private Integer tbCheck;
/**
* @param
* @return
* @author ywy
* @Description Enterprise 转换成 EnterpriseVO
* @date 2024/10/15 13:44
*/
public static EnterpriseVO convertToVO(Enterprise enterprise) {
if (enterprise == null) {
return null;
}
EnterpriseVO vo = new EnterpriseVO();
vo.setEnterpriseId(enterprise.getId());
vo.setEnterpriseName(enterprise.getEnterpriseName());
vo.setEnterpriseAbbreviationName(enterprise.getEnterpriseAbbreviationName());
vo.setParentId(enterprise.getParentId());
vo.setArchivingStatus(enterprise.getArchivingStatus());
vo.setCompletionStatus(enterprise.getCompletionStatus());
vo.setEnterpriseType(enterprise.getEnterpriseType());
vo.setMnemonicCode(enterprise.getMnemonicCode());
vo.setTaxpayerIdentificationNumber(enterprise.getTaxpayerIdentificationNumber());
vo.setEnterpriseCity(enterprise.getEnterpriseCity());
vo.setEnterpriseProvince(enterprise.getEnterpriseProvince());
vo.setReportDate(enterprise.getReportDate());
vo.setEnterpriseGroup(enterprise.getEnterpriseGroup());
vo.setPeriodWhichBelongsStart(enterprise.getPeriodWhichBelongsStart());
vo.setPeriodWhichBelongsEnd(enterprise.getPeriodWhichBelongsEnd());
vo.setSignatureAnnotator(enterprise.getSignatureAnnotator());
vo.setReportDate(enterprise.getReportDate());
vo.setSort(enterprise.getSort());
return vo;
}
/**
* @param enterpriseVO
* @return Enterprise
* @author ywy
* @Description EnterpriseVO 转换成 Enterprise
* @date 2024/10/15 13:44
*/
public static Enterprise convertToVO(EnterpriseVO enterpriseVO) {
if (enterpriseVO == null) {
return null;
}
Enterprise enterprise = new Enterprise();
enterprise.setId(enterpriseVO.getEnterpriseId());
enterprise.setEnterpriseName(enterpriseVO.getEnterpriseName());
enterprise.setEnterpriseAbbreviationName(enterpriseVO.getEnterpriseAbbreviationName());
enterprise.setParentId(enterpriseVO.getParentId());
enterprise.setArchivingStatus(enterpriseVO.getArchivingStatus());
enterprise.setCompletionStatus(enterpriseVO.getCompletionStatus());
enterprise.setEnterpriseType(enterpriseVO.getEnterpriseType());
enterprise.setMnemonicCode(enterpriseVO.getMnemonicCode());
enterprise.setTaxpayerIdentificationNumber(enterpriseVO.getTaxpayerIdentificationNumber());
enterprise.setEnterpriseCity(enterpriseVO.getEnterpriseCity());
enterprise.setEnterpriseProvince(enterpriseVO.getEnterpriseProvince());
enterprise.setPeriodWhichBelongsStart(enterpriseVO.getPeriodWhichBelongsStart());
enterprise.setPeriodWhichBelongsEnd(enterpriseVO.getPeriodWhichBelongsEnd());
enterprise.setSignatureAnnotator(enterpriseVO.getSignatureAnnotator());
enterprise.setReportDate(enterpriseVO.getReportDate());
enterprise.setEnterpriseGroup(enterpriseVO.getEnterpriseGroup());
enterprise.setSort(enterpriseVO.getSort());
return enterprise;
}
private static void buildChildrenTree(EnterpriseVO parent, Map<String, EnterpriseVO> allEnterprise) {
if (parent.getChildren() == null) {
parent.setChildren(new ArrayList<>());
}
for (EnterpriseVO enterprise : allEnterprise.values()) {
if (enterprise.getParentId() != null && enterprise.getParentId().equals(parent.getEnterpriseId())) {
parent.getChildren().add(enterprise);
// 递归构建当前子节点的子树
buildChildrenTree(enterprise, allEnterprise);
}
}
}
private static List<EnterpriseVO> getAllChildren(EnterpriseVO parent, Map<String, EnterpriseVO> enterpriseMap) {
List<EnterpriseVO> children = new ArrayList<>();
if (parent.getChildren() != null) {
for (EnterpriseVO child : parent.getChildren()) {
children.add(child);
// 递归获取当前子节点的所有子节点
children.addAll(getAllChildren(child, enterpriseMap));
}
}
return children;
}
/**
* @param
* @return
* @author ywy
* @Description 获取所有客户的树
* @date 2024/11/22 18:22
*/
public static Map<Long, EnterpriseVO> buildTreeMap(Map<String, EnterpriseVO> allEnterprise) {
Map<Long, EnterpriseVO> treeMap = new ConcurrentHashMap<>();
List<EnterpriseVO> rootCandidates = new ArrayList<>();
// 首先,将所有企业对象放入treeMap中,以便后续可以通过ID快速查找
for (EnterpriseVO enterprise : allEnterprise.values()) {
treeMap.put(enterprise.getEnterpriseId(), enterprise);
}
// 遍历映射中的每个企业对象
for (EnterpriseVO enterprise : allEnterprise.values()) {
Long parentId = enterprise.getParentId();
if (parentId == 0 || parentId == null) {
// 如果parentId为0或者为null,则视为根节点
rootCandidates.add(enterprise);
} else {
// 否则,将当前企业对象添加到其父节点的子节点列表中
EnterpriseVO parent = treeMap.get(parentId);
if (parent != null) {
parent.getChildren().add(enterprise);
} else {
rootCandidates.add(enterprise);
}
}
}
return treeMap;
}
/**
* @param enterpriseMap
* @return List<EnterpriseVO>
* @author ywy
* @Description 递归构建树方法,只展示最顶层的客户树
* @date 2024/10/11 11:35
*/
public static List<EnterpriseVO> buildTree(Map<String, EnterpriseVO> enterpriseMap) {
try {
List<EnterpriseVO> rootNodes = new ArrayList<>();
// 遍历映射中的每个企业对象
for (EnterpriseVO enterprise : enterpriseMap.values()) {
String parentId = String.valueOf(enterprise.getParentId());
if (parentId.equals(0) || !StringUtils.hasText(parentId)) {
// 如果parentId为null或者父节点不存在于映射中(可能是数据不完整),则视为根节点
rootNodes.add(enterprise);
} else {
// 否则,将当前企业对象添加到其父节点的子节点列表中
EnterpriseVO parent = enterpriseMap.get(parentId);
if (parent != null) {
parent.getChildren().add(enterprise);
} else {
rootNodes.add(enterprise);
}
}
}
// 对根节点进行排序
rootNodes.sort(Comparator.comparingInt(EnterpriseVO::getSort));
// 对每个根节点的子节点进行排序
for (EnterpriseVO rootNode : rootNodes) {
sortChildren(rootNode);
}
return rootNodes;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("构建客户树发生异常");
}
}
/**
* @param
* @return
* @author ywy
* @Description 构建某个节点下的所有子节点,平铺在同一层级上去
* @date 2024/12/19 15:20
*/
public static List<EnterpriseVO> buildList(EnterpriseVO enterpriseVO) {
List<EnterpriseVO> allEnterprises = new ArrayList<>();
addAllEnterprises(enterpriseVO, allEnterprises);
return allEnterprises;
}
private static void addAllEnterprises(EnterpriseVO enterpriseVO, List<EnterpriseVO> allEnterprises) {
// 首先添加当前节点
allEnterprises.add(enterpriseVO);
// 然后递归地添加所有子节点
List<EnterpriseVO> children = enterpriseVO.getChildren();
if (children != null) {
for (EnterpriseVO child : children) {
addAllEnterprises(child, allEnterprises);
}
}
}
private static void sortChildren(EnterpriseVO node) {
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
node.getChildren().sort(Comparator.comparingInt(EnterpriseVO::getSort));
// 递归地对每个子节点的子节点进行排序
for (EnterpriseVO child : node.getChildren()) {
sortChildren(child);
}
}
}
/**
* @param enterpriseMap
* @param topId
* @return
* @author ywy
* @Description 从一个企业树结构中复制并生成一个新的企业树结构
* @date 2024/10/31 13:34
*/
public static List<EnterpriseVO> copyEnterpriseTreeWithNewParentId(Map<String, EnterpriseVO> enterpriseMap, String topId) {
SnowflakeIdGenerator idWorker = new SnowflakeIdGenerator(0, 0);
Map<String, String> oldToNewIdMap = new ConcurrentHashMap<>();
List<EnterpriseVO> copiedTree = new ArrayList<>();
Long groupId = null;
// 直接处理顶级客户节点
EnterpriseVO topEnterprise = enterpriseMap.get(topId);
if (topEnterprise != null) {
String newTopId = String.valueOf(idWorker.nextId());
groupId = Long.valueOf(newTopId);
oldToNewIdMap.put(topId, newTopId);
EnterpriseVO copiedTopEnterprise = new EnterpriseVO();
copiedTopEnterprise.setEnterpriseId(Long.valueOf(newTopId));
copiedTopEnterprise.setParentId(0L);
copiedTopEnterprise.setEnterpriseName(topEnterprise.getEnterpriseName());
copiedTopEnterprise.setTaxpayerIdentificationNumber(topEnterprise.getTaxpayerIdentificationNumber());
copiedTopEnterprise.setBusinessType(topEnterprise.getBusinessType());
copiedTopEnterprise.setArchivingStatus(topEnterprise.getArchivingStatus());
copiedTopEnterprise.setEnterpriseAbbreviationName(topEnterprise.getEnterpriseAbbreviationName());
copiedTopEnterprise.setSignatureAnnotator(topEnterprise.getSignatureAnnotator());
copiedTopEnterprise.setReportDate(topEnterprise.getReportDate());
copiedTopEnterprise.setEnterpriseGroup(groupId);
copiedTopEnterprise.setSort(topEnterprise.getSort());
copiedTree.add(copiedTopEnterprise);
// 使用DFS复制子节点
Deque<String> stack = new ArrayDeque<>();
stack.addAll(enterpriseMap.keySet().stream()
.filter(key -> enterpriseMap.get(key).getParentId().equals(topEnterprise.getEnterpriseId()))
.collect(Collectors.toList()));
while (!stack.isEmpty()) {
String currentOldId = stack.pop();
if (!oldToNewIdMap.containsKey(currentOldId)) {
String currentNewId = String.valueOf(idWorker.nextId());
oldToNewIdMap.put(currentOldId, currentNewId);
EnterpriseVO currentEnterprise = enterpriseMap.get(currentOldId);
EnterpriseVO copiedEnterprise = new EnterpriseVO();
copiedEnterprise.setEnterpriseId(Long.valueOf(currentNewId));
copiedEnterprise.setParentId(Long.valueOf(oldToNewIdMap.get(String.valueOf(currentEnterprise.getParentId()))));
copiedEnterprise.setEnterpriseName(currentEnterprise.getEnterpriseName());
copiedEnterprise.setTaxpayerIdentificationNumber(currentEnterprise.getTaxpayerIdentificationNumber());
copiedEnterprise.setBusinessType(currentEnterprise.getBusinessType());
copiedEnterprise.setArchivingStatus(currentEnterprise.getArchivingStatus());
copiedEnterprise.setEnterpriseAbbreviationName(currentEnterprise.getEnterpriseAbbreviationName());
copiedEnterprise.setSignatureAnnotator(currentEnterprise.getSignatureAnnotator());
copiedEnterprise.setReportDate(currentEnterprise.getReportDate());
copiedEnterprise.setEnterpriseGroup(groupId);
copiedEnterprise.setSort(currentEnterprise.getSort());
copiedTree.add(copiedEnterprise);
stack.addAll(enterpriseMap.keySet().stream()
.filter(key -> enterpriseMap.get(key).getParentId().equals(currentEnterprise.getEnterpriseId()))
.collect(Collectors.toList()));
}
}
} else {
// 处理顶级客户节点不存在的情况
// 可以抛出异常或返回空列表等
System.out.println("Top enterprise with ID " + topId + " not found.");
}
return copiedTree;
}
/**
* @param
* @return
* @author ywy
* @Description 获取所有 children 不为空的节点列表,并按深度排序(最下层的节点在最前面)
* @date 2024/11/23 16:58
*/
public static List<EnterpriseNodeWrapper> getAllNonEmptyChildrenNodesSortedByDepth(EnterpriseVO root) {
List<EnterpriseNodeWrapper> resultWrappers = new ArrayList<>();
findNonEmptyChildrenNodes(root, 0, resultWrappers);
// 根据深度对结果进行排序,深度越大的排在越后面
Collections.sort(resultWrappers, Comparator.comparingInt(EnterpriseNodeWrapper::getDepth).reversed());
return resultWrappers;
}
private static void findNonEmptyChildrenNodes(EnterpriseVO root, int depth, List<EnterpriseNodeWrapper> result) {
if (root == null) {
return;
}
// 检查当前节点是否为最低合并节点
if (root.getChildren().isEmpty()) {
root.setIsLowestMerge(true);
} else {
boolean flag = true;
for (EnterpriseVO child : root.getChildren()) {
if (!child.getChildren().isEmpty()) {
root.setIsLowestMerge(false);
flag = false;
break;
}
}
if (flag) {
root.setIsLowestMerge(flag);
}
}
// 如果当前节点的 children 不为空,则包装并添加到结果列表中
if (!root.getChildren().isEmpty()) {
result.add(new EnterpriseNodeWrapper(root, depth));
}
// 递归遍历所有子节点,深度加1
for (EnterpriseVO child : root.getChildren()) {
findNonEmptyChildrenNodes(child, depth + 1, result);
}
}
} `
`
<if test="enterpriseVO.periodWhichBelongsStart != null">
AND t1.period_which_belongs_start >= #{enterpriseVO.periodWhichBelongsStart}
<if test="enterpriseVO.periodWhichBelongsEnd != null">
AND
</if>
</if>
<if test="enterpriseVO.periodWhichBelongsEnd != null">
t1.period_which_belongs_end <= #{enterpriseVO.periodWhichBelongsEnd}
</if>
<if test="enterpriseVO.archivingStatus != null">
t1.archiving_status = #{enterpriseVO.archivingStatus}
</if>
<if test="enterpriseVO.mnemonicCode != null and enterpriseVO.mnemonicCode != ''">
AND t1.mnemonic_code LIKE CONCAT('%', #{enterpriseVO.mnemonicCode}, '%')
</if>
<if test="enterpriseVO.businessType != null">
AND t1.business_type = #{enterpriseVO.businessType}
</if>
<if test="enterpriseVO.parentId != null">
AND t1.parent_id = #{enterpriseVO.parentId}
</if>
<if test="enterpriseVO.userId != null">
AND t2.user_id = #{enterpriseVO.userId}
</if>
<if test="enterpriseVO.userName != null and enterpriseVO.userName != ''">
AND t3.user_name LIKE CONCAT('%', #{enterpriseVO.userName}, '%')
</if>
<if test="enterpriseVO.nickName != null and enterpriseVO.nickName != ''">
AND t3.nick_name LIKE CONCAT('%', #{enterpriseVO.nickName}, '%')
</if>
</where>
ORDER BY t1.enterprise_name ASC,t1.period_which_belongs_end DESC
</select>`
`
<collection property="users" ofType="com.fengjun.finance.vo.UserVO">
<id property="userId" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="mobile" column="mobile"/>
<result property="nickName" column="nick_name"/>
<result property="userType" column="user_type"/>
</collection>
</resultMap>`
controller 请求过来,循环查询相同的条件,会自动启用缓存,但是bean 里面这个 private List
详细堆栈日志
jdk21 虚拟线程
Comment From: miemieYaho
给出git形式的最小复现demo