最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java EasyExcel實現(xiàn)動態(tài)列解析和存表

 更新時間:2023年06月15日 17:28:32   作者:我是一顆小虎牙_  
這篇文章主要為大家介紹了java EasyExcel實現(xiàn)動態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

背景

一個表中的數(shù)據(jù)來源于多個其他系統(tǒng)的導(dǎo)出表,其中的特點就是大多數(shù)的字段都是一樣的(可能導(dǎo)出的表頭不一樣),只有部分少數(shù)字段是每個系統(tǒng)自己獨有的。圍繞這個做一次功能性分析

分析:大多數(shù)字段是一樣的,那么就是實際的表字段,唯一的區(qū)別就是各系統(tǒng)內(nèi)的名字可能不一樣,少數(shù)每個系統(tǒng)獨有的字段,可以歸為動態(tài)字段。

總結(jié):

  • 公共字段(翻譯表頭:@ExcelProperty 可以指定多個表頭( @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"}) ))
  • 動態(tài)字段(需要有每個系統(tǒng)內(nèi)動態(tài)字段的字段名稱和表頭的對應(yīng)關(guān)系,考慮使用字典,供業(yè)務(wù)員配置,后續(xù)如果新添加其他動態(tài)字段直接在字典中配置,無需另行開發(fā))

注意:由于無法控制和預(yù)料固定字段在新接入的系統(tǒng)中的實際表頭,所以如果新接入系統(tǒng)的公共表頭與表字段不一致,需要在 @ExcelProperty(value = {}) 中添加新的表頭

效果

字典配置:

數(shù)據(jù)表結(jié)果:

公共字段使用常規(guī)的數(shù)據(jù)庫表字段存儲,動態(tài)字段使用額外列存 JSON 串。

代碼

引入pom坐標(biāo)

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.0</version>
</dependency>

創(chuàng)建實體類

public class AgentDeliverOrderImportVo {
    @ExcelProperty(value = {"訂單編號"}, order = 1)
    private String deliverNo;
    @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"}, order = 14)
    @ColumnName(name = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"})
    private Integer deliverCount;
    /**
     * 動態(tài)字段(業(yè)務(wù)線編號區(qū)分)
     */
    private String dynamicFields;
    private Date createTime;
    private String createBy;
}
  • 因為存在不確定的列,所以只能使用 EasyExcel 的不創(chuàng)建對象的寫,那么
public String test(MultipartFile file) throws IOException {
    //假設(shè)從字典中獲取字典值
    Map<String, String> dictMap = new HashMap<>();
    dictMap.put("項目", "xm");
    dictMap.put("嗨一付訂單編號", "hyfddbh");
    try (InputStream inputStream = file.getInputStream()) {
        EasyExcel.read(inputStream, new ReadListener<Map<String, String>>(){
            private Map<Integer, String> fieldHead;
            //獲取表頭
            @Override
            public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
                Map<Integer, String> integerStringMap = ConverterUtils.convertToStringMap(headMap, context);
                log.info("解析到一條頭數(shù)據(jù):{}", JSON.toJSONString(integerStringMap));
                fieldHead = ExcelParsing.setFieldHead(integerStringMap, AgentDeliverOrderImportVo.class);
                log.info("轉(zhuǎn)化后頭數(shù)據(jù):{}", JSONObject.toJSONString(fieldHead));
            }
            //獲取數(shù)據(jù)
            @Override
            public void invoke(Map<String, String> map, AnalysisContext analysisContext) {
                log.info("解析到一條數(shù)據(jù):{}", JSON.toJSONString(map));
                Map<String, String> valueMap = ExcelParsing.setFieldValue(fieldHead, dictMap, map);
                log.info("轉(zhuǎn)化一條數(shù)據(jù):{}", JSONObject.toJSONString(valueMap));
                log.info("轉(zhuǎn)化一條動態(tài)數(shù)據(jù):{}", JSONObject.toJSONString(ExcelParsing.getValueMap(valueMap, AgentDeliverOrderImportVo.class)));
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            }
        }).sheet().doRead();
    }
    return "完成";
}
/**
 * @author Surpass
 * @Description: excel處理類
 * @date 27/07/2022 15:04
 */
class ExcelParsing {
    /**
     * 將公共字段中的中文轉(zhuǎn)換成數(shù)據(jù)庫表字段,動態(tài)字段(其他字段保留)
     * @param headMap               {1:"姓名", 2:"年齡"}
     * @param obj                   AgentDeliverOrderImportVo(導(dǎo)入實體類)
     * @return java.util.Map<java.lang.String, java.lang.String>       {1:"name", 2:"年齡"}
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<Integer, String> setFieldHead(Map<Integer, String> headMap, Class<?> obj) {
        Field[] fields = obj.getDeclaredFields();
        for (Field field : fields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation == null) {
                continue;
            }
            //存在翻譯字段的情況,一個字段對應(yīng)好幾個表頭(盡量避免)
            List<String> valueList = Arrays.asList(annotation.value());
            for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                if (valueList.contains(entry.getValue())) {
                    headMap.put(entry.getKey(), field.getName());
                }
            }
        }
        return headMap;
    }
    /**
     * 獲取數(shù)據(jù)(平鋪),指動態(tài)字段kv和公共字段kv在同一級
     * @param headMap               {1:"name", 2:"年齡"}
     * @param dictMap               {"年齡":"age"}
     * @param valueMap              {1:"廣州****公司", 2:"23"}
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<String, String> setFieldValue(Map<Integer, String> headMap,
                                                    Map<String, String> dictMap,
                                                    Map<String, String> valueMap) {
        Map<Integer, String> valueIntegerMap = valueMap.entrySet().stream().collect(
                Collectors.toMap(item -> Integer.valueOf(String.valueOf(item.getKey())),
                        item -> StrUtil.nullToEmpty(item.getValue()))
        );
        Map<String, String> valueResultMap = new HashMap<>(valueMap.size());
        Iterator<Map.Entry<Integer, String>> iterator = valueIntegerMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            //動態(tài)字段
            if (dictMap != null && dictMap.containsKey(headMap.get(entry.getKey()))) {
                valueResultMap.put(dictMap.get(headMap.get(entry.getKey())), entry.getValue());
                continue;
            }
            //公共字段
            valueResultMap.put(headMap.get(entry.getKey()), entry.getValue());
            iterator.remove();
        }
        return valueResultMap;
    }
    /**
     * 獲取數(shù)據(jù)(表結(jié)構(gòu)),指動態(tài)字段kv已經(jīng)加入到數(shù)據(jù)庫表字段 dynamicFields 中
     * @param obj                   AgentDeliverOrderImportVo(導(dǎo)入實體類)
     * @param valueMap              {"name":"廣州****公司", "age":"23"}
     * @return java.util.Map<java.lang.String, java.lang.String>  
     * 返回結(jié)果: {"name":"廣州****公司","dynamicFields":{"age":"23"}}
     * @author Surpass
     * @date 01/08/2022 17:10
     */
    public static Map<String, Object> getValueMap(Map<String, String> valueMap,
                                                  Class<?> obj) {
        Map<String, Object> resultMap = new HashMap<>(valueMap);
        List<String> commonFieldList = new ArrayList<>();
        Field[] fields = obj.getDeclaredFields();
        for (Field field : fields) {
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            if (annotation == null) {
                continue;
            }
            commonFieldList.add(field.getName());
        }
        //過濾掉實體中的公共字段
        Map<String, String> dynamicMap = valueMap.entrySet().stream()
                .filter(item -> !commonFieldList.contains(item.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        resultMap.put("dynamicFields", dynamicMap);;
        return resultMap;
    }
}

經(jīng)過解析以后這個文檔的數(shù)據(jù)已經(jīng)和數(shù)據(jù)庫表一致了,那么我們后續(xù)的操作就是常規(guī)的校驗和插入邏輯了。

目前有一個缺點就是這樣存的動態(tài)字段不好做條件查詢,影響不是很大。

總結(jié)

本文介紹了使用 EasyExcel 組件來進(jìn)行導(dǎo)入,實現(xiàn)公共列和動態(tài)列組合類型的導(dǎo)入,以及如何存儲的功能,主要利用反射和字典分別來維護(hù)公共列和動態(tài)列的表頭和字段的對應(yīng)關(guān)系,利用此關(guān)系對數(shù)據(jù)進(jìn)行解析。

以上就是java EasyExcel實現(xiàn)動態(tài)列解析和存表的詳細(xì)內(nèi)容,更多關(guān)于java EasyExcel動態(tài)列存表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java調(diào)用本地庫的JNA快速入門教程

    Java調(diào)用本地庫的JNA快速入門教程

    JNA(Java Native Access)是Java庫,簡化調(diào)用操作系統(tǒng)API,本文通過一個示例項目展示了如何使用JNA與C/C++編寫的DLL交互,包括定義原生接口、數(shù)據(jù)類型映射、指針和引用的處理、結(jié)構(gòu)體的使用以及異常處理等,感興趣的朋友一起看看吧
    2025-09-09
  • java連接Mysql數(shù)據(jù)庫的工具類

    java連接Mysql數(shù)據(jù)庫的工具類

    這篇文章主要介紹了java連接Mysql數(shù)據(jù)庫的工具類,非常的實用,推薦給大家,需要的朋友可以參考下
    2015-03-03
  • 解決idea 項目編譯后沒有class文件的問題

    解決idea 項目編譯后沒有class文件的問題

    這篇文章主要介紹了解決idea 項目編譯后沒有class文件的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程

    2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程

    IDEA是用于java語言開發(fā)的集成環(huán)境,并且經(jīng)常用于maven、spring、MyBatis等項目的開發(fā),下面這篇文章主要給大家介紹了關(guān)于2022版IDEA創(chuàng)建一個maven項目的超詳細(xì)圖文教程,需要的朋友可以參考下
    2023-02-02
  • Java中實現(xiàn)OCR識別讀取圖片中的文字

    Java中實現(xiàn)OCR識別讀取圖片中的文字

    圖片內(nèi)容一般無法編輯,如果想要讀取圖片中的文本,我們需要用到OCR工具,本文將介紹如何在Java中實現(xiàn)OCR識別讀取圖片中的文字,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • Maven 的配置文件路徑讀取方法

    Maven 的配置文件路徑讀取方法

    這篇文章主要介紹了Maven 的配置文件路徑讀取方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 詳解Spring FactoryBean靈活創(chuàng)建復(fù)雜對象的秘密武器

    詳解Spring FactoryBean靈活創(chuàng)建復(fù)雜對象的秘密武器

    FactoryBean是Spring框架中用于創(chuàng)建復(fù)雜Bean的接口,通過編程方式控制Bean的創(chuàng)建過程,它允許開發(fā)者自定義Bean的創(chuàng)建邏輯,適用于集成第三方庫、延遲初始化、動態(tài)代理和統(tǒng)一管理資源等場景,本文介紹Spring FactoryBean創(chuàng)建復(fù)雜對象的相關(guān)操作,感興趣的朋友一起看看吧
    2025-02-02
  • mybatis自動掃描和自定義類注解方式

    mybatis自動掃描和自定義類注解方式

    這篇文章主要介紹了mybatis自動掃描和自定義類注解方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 在macOS上安裝jenv管理JDK版本的詳細(xì)步驟

    在macOS上安裝jenv管理JDK版本的詳細(xì)步驟

    jEnv是一個命令行工具,正如它的官網(wǎng)所宣稱的那樣,它是來讓你忘記怎么配置JAVA_HOME環(huán)境變量的神隊友,這篇文章主要介紹了在macOS上安裝jenv管理JDK版本的詳細(xì)步驟,需要的朋友可以參考下
    2025-07-07
  • IDEA Error:java: 無效的源發(fā)行版: 17錯誤

    IDEA Error:java: 無效的源發(fā)行版: 17錯誤

    本文主要介紹了IDEA Error:java: 無效的源發(fā)行版: 17錯誤,這個錯誤是因為您的IDEA編譯器不支持Java 17版本,您需要更新您的IDEA編譯器或者將您的Java版本降級到IDEA支持的版本,本文就來詳細(xì)的介紹一下
    2023-08-08

最新評論

朝阳区| 揭阳市| 海阳市| 勃利县| 南郑县| 繁峙县| 景洪市| 平定县| 唐海县| 韩城市| 绥江县| 施秉县| 广东省| 阿克苏市| 望谟县| 望奎县| 安龙县| 北宁市| 盘锦市| 潍坊市| 萨嘎县| 咸宁市| 寿光市| 曲靖市| 宁津县| 伊宁县| 义马市| 南投县| 宁波市| 禹州市| 基隆市| 新乡县| 延安市| 彰武县| 西林县| 科尔| 宜兰县| 色达县| 于都县| 蕉岭县| 老河口市|