1. 程式人生 > >MySql、Oracle(通用方法)遞迴查詢生成檔案目錄樹(JAVA實現 遞迴過程中不訪問資料庫,遞迴之前只訪問兩次 進行遞迴前資料準備)

MySql、Oracle(通用方法)遞迴查詢生成檔案目錄樹(JAVA實現 遞迴過程中不訪問資料庫,遞迴之前只訪問兩次 進行遞迴前資料準備)

查詢檔案樹

實體類

public class TradeInfoFile {
​
    // 檔案編碼(子)
    private String fileCode;
    // 所屬檔案編碼(父)
    private String belongFileCode;
    // 交易資訊編碼
    private String finTradeCode;
    // 是否是資料夾
    private Boolean isDirFlag;
    //最後修改時間
    private Date lastModifyTime;
    private String fmtLastModifyTime;
    /*
      children屬性不與資料庫中TRADER_INFO_FILE標建立對映關係
    */
    @Transient
    private List<TradeInfoFile> children;
    //省略set/get方法.......................

    // 建立檔案根節點
    public static TradeInfoFile createRoot(List<TradeInfoFile> fileTree) {
      TradeInfoFile root = new TradeInfoFile();
      root.setFileCode("-1");
      root.setBelongFileCode("根節點");
      root.setChildren(fileTree);
      return root;
    }
}

 

Controller層

@RestController
@RequestMapping("/trade-file")
public class TradeInfoController {
​
    @Autowired
    private TradeInfoService tradeInfoService;
    
    // 查詢檔案樹,一個交易資訊編碼可以對應多個檔案和資料夾
    @GetMapping(value = "/{id}/file-tree") // 交易資訊編碼
    public TradeInfoFile getFileTree(@RequestParam(name = "id") String finTradeCode) {
        return tradeInfoService.getFileTree(finTradeCode);
    }
}

 

Service層

public interface TradeInfoService {
    public TradeInfoFile getFileTree(String finTradeCode);
}
​
@Service
public class TradeInfoFileServiceImpl implements TradeInfoService{
​
    @Autowired
    private TradeInfoFileMapper tradeInfoFileMapper;
    
    @Override
    // 查詢目錄樹
    public TradeInfoFile getFileTree(String finTradeCode) {
        
        /*
         * 思路:為了減輕資料庫的壓力,減少資料庫的訪問次數,採用少次訪問資料庫獲得檔案樹的資料,存放在
         *      Map中,遞迴時,從Map中取數,不在訪問資料庫
         * 引數準備:
         * rootMap:根目錄所有檔案和資料夾(遞迴時,下一級檔案裡一層的檔案和資料夾)
         *      Map<fileCode, tradeInfoFile>
         * allMap:所有檔案和資料夾
         *      Map<fileCode, tradeInfoFile>
         * allBelongFileCodeMap:以belongFileCode為key對應的Map集合
         *      Map<belongFileCode, Map<fileCode, tradeInfoFile>>
         */
        Map<String, TradeInfoFile> rootMap = new HashMap<>();
        Map<String, TradeInfoFile> allMap = new HashMap<>();
        Map<String, Map<String, TradeInfoFile>> allBelongFileCodeMap = new HashMap<>();
        getParameterMap(finTradeCode, rootMap, allMap, allBelongFileCodeMap);
        
        // 呼叫遞迴方法,
        List<TradeInfoFile> tempTree = getTree(rootMap, allMap, allBelongFileCodeMap);
        
        List<TradeInfoFile> tree = new ArrayList<>();
        TradeInfoFile tradeInfoFile = TradeInfoFile.createRoot(tree);
        
        // 解除地址引用
        for (TradeInfoFile item : tempTree) {
            tree.add(item);
        }
        return tradeInfoFile;
    }
    
    // 遞迴查詢生成目錄樹
    private List<TradeInfoFile> getTree(Map<String, TradeInfoFile> rootMap, Map<String, TradeInfoFile> allMap, 
            Map<String, Map<String, TradeInfoFile>> allBelongFileCodeMap){
        
        // 臨時檔案樹
        List<TradeInfoFile> tempTree = new ArrayList<>();
        for (String fileCode : rootMap.keySet()) {
            TradeInfoFile tradeInfoFile = rootMap.get(fileCode);
            /*
             * 資料夾:
             *   非空資料夾:繼續遞迴
             *   空資料夾:新增到檔案樹中
             * 檔案:
             *   新增到檔案樹中
             */
            if(tradeInfoFile.getIsDirFlag()) { //資料夾
                /*
                 *  獲取當前資料夾裡 的一層的 檔案和資料夾 nextRootMap,作為遞迴的引數
                 */
                Map<String, TradeInfoFile> nextRootMap = allBelongFileCodeMap.get(fileCode);
                if(null != nextRootMap){ // 非空資料夾
                    List<TradeInfoFile> childrenTree = getTree(nextRootMap, allMap, allBelongFileCodeMap);
                    tradeInfoFile.setChildren(childrenTree);
                }
            } 
            tempTree.add(tradeInfoFile);
        }       
        // 對查詢出來的檔案樹 進行排序
        Collections.sort(tempTree, new Comparator<TradeInfoFile>() {
​
            @Override
            public int compare(TradeInfoFile o1, TradeInfoFile o2) {
                // 同級目錄  優先按資料夾排序 降序
                if(!o2.getIsDirFlag().equals(o1.getIsDirFlag())){
                    return o2.getIsDirFlag().compareTo(o1.getIsDirFlag());
                }
                //其次 按照 最後修改時間 排序 倒序
                return o2.getLastModifyTime().compareTo(o1.getLastModifyTime());
            }
        });
        return tempTree;
    }
    
    // 遞迴查詢目錄樹前引數準備
    private void getParameterMap(String finTradeCode, Map<String, TradeInfoFile> rootMap,
            Map<String, TradeInfoFile> allMap, Map<String, Map<String, TradeInfoFile>> allBelongFileCodeMap) {
        // 查詢  所有 檔案和資料夾
        TradeInfoFile entity = new TradeInfoFile();
        entity.setFinTradeCode(finTradeCode);
        List<TradeInfoFile> allEntitys = tradeInfoFileMapper.selectByEntity(entity);
        
        // 查詢根目錄下的 所有 檔案和資料夾
        entity.setBelongFileCode("0");
        List<TradeInfoFile> rootEntitys = tradeInfoFileMapper.selectByEntity(entity);
        
        for (TradeInfoFile item : allEntitys) {
            String fileCode = item.getFileCode();
            String belongFileCode = item.getBelongFileCode();
            
            // 檔案時間格式化
            item.setFmtLastModifyTime(new SimpleDateFormat("YYYY-MM-DD").format(item.getLastModifyTime()));
            allMap.put(fileCode, item);
            
            // 第一次,allBelongFileCodeMap中對應K=belongFileCode的value為null;所以,new HashMap一次,給一個地址,後續使用好往裡面塞值(put進去)
            if(null == allBelongFileCodeMap.get(belongFileCode)){
                allBelongFileCodeMap.put(belongFileCode, new HashMap<String, TradeInfoFile>());
            }
            /*
             * Map<String, Map<String, TradeInfoFile>>  allBelongFileCodeMap
             * Map是引用型別,allBelongFileCodeMap.get(belongFileCode)取出是一個Map,
             * allBelongFileCodeMap.get(belongFileCode).put(fileCode, item);
             * 就可以使allBelongFileCodeMap中belongFileCode對應value:map的值發生變化;(主要是地址的引用)
             */
            allBelongFileCodeMap.get(belongFileCode).put(fileCode, item);
        }
        
        for (TradeInfoFile item : rootEntitys) {
            // 檔案時間格式化
            item.setFmtLastModifyTime(new SimpleDateFormat("YYYY-MM-DD").format(item.getLastModifyTime()));
            rootMap.put(item.getFileCode(), item);
        }
    }
}
​