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

SpringBoot整合EasyExcel實(shí)現(xiàn)批量導(dǎo)入導(dǎo)出

 更新時(shí)間:2024年03月20日 09:36:41   作者:避暑人  
這篇文章主要為大家詳細(xì)介紹了SpringBoot整合EasyExcel實(shí)現(xiàn)批量導(dǎo)入導(dǎo)出功能的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),需要的小伙伴可以參考下

不用Mybatis的原因就是因?yàn)樵诖罅繑?shù)據(jù)插入的時(shí)候jdbc性能比mybatis好

1. 首先分批讀取Excel中的數(shù)據(jù) 這一點(diǎn)EasyExcel有自己的解決方案

2.其次就是DB里插入,怎么去插入這20w條數(shù)據(jù) 當(dāng)然不能一條一條循環(huán),應(yīng)該批量插入20w條數(shù)據(jù)

3.使用JDBC+事務(wù)的批量操作將數(shù)據(jù)插入到數(shù)據(jù)庫

整個(gè)Demo連接,打開下載即可,包含數(shù)據(jù)庫表

為什么mybatis的foreach比JDBC的addBatch慢

ORM 框架開銷:MyBatis 的 foreach 操作涉及到將對(duì)象數(shù)據(jù)轉(zhuǎn)換為 SQL 語句的過程,在這個(gè)過程中需要進(jìn)行對(duì)象到 SQL 的映射、動(dòng)態(tài) SQL 的解析等操作,這些額外的操作會(huì)增加開銷。

數(shù)據(jù)庫連接管理:MyBatis 在執(zhí)行 foreach 操作時(shí),會(huì)頻繁地獲取和釋放數(shù)據(jù)庫連接,而數(shù)據(jù)庫連接的獲取和釋放是一個(gè)相對(duì)耗時(shí)的操作,特別在百萬級(jí)數(shù)據(jù)的情況下,這種開銷可能會(huì)積累導(dǎo)致性能下降。

SQL 語句生成:MyBatis 的 foreach 操作在執(zhí)行過程中會(huì)生成大量的 SQL 語句,這可能會(huì)導(dǎo)致數(shù)據(jù)庫的緩存失效、重新編譯查詢計(jì)劃等,從而影響性能。

批量插入優(yōu)化:JDBC 的 addBatch 可以直接利用底層數(shù)據(jù)庫的批量插入功能,而 MyBatis 的 foreach 操作在某些數(shù)據(jù)庫上可能不能充分利用數(shù)據(jù)庫的批量插入優(yōu)化。

1.引入依賴

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.42</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.18</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

2.Controller層

@Slf4j
@RestController
@RequestMapping("excel")
public class ExcelController {
 
    @Autowired
    private UserService userService;
 
    //導(dǎo)出
    @GetMapping("/exportExcel")
    public String exportExcel(HttpServletRequest request, HttpServletResponse response){
        String file="D:";
        long startTime = System.currentTimeMillis();
        log.debug("-------------開始插入-------------------");
        userService.exportInspectionPlan(request,response);
        return "ok";
    }
 
 
    //導(dǎo)入
    @PostMapping("/importExcel")
    public void importExcel(MultipartFile multipartFile) throws IOException {
        if (multipartFile.isEmpty()) {
            return;
        }
        // 這里 需要指定讀用哪個(gè)class去讀,然后讀取第一個(gè)sheet 文件流會(huì)自動(dòng)關(guān)閉
        // 這里每次會(huì)讀取3000條數(shù)據(jù) 然后返回過來 直接調(diào)用使用數(shù)據(jù)就行
        EasyExcel.read(multipartFile.getInputStream(), ExportPlanInformationVo.class,
            new PageReadListener<ExportPlanInformationVo>(dataList -> {
                            for (ExportPlanInformationVo user : dataList) {
                                //將導(dǎo)入的數(shù)據(jù)用mybatisPlus一個(gè)個(gè)添加進(jìn)數(shù)據(jù)庫
                                System.out.println(user);
                            }
        })).sheet("現(xiàn)場(chǎng)巡視計(jì)劃報(bào)表").doRead();
    }
    /**
     * 1. 首先分批讀取Excel中的數(shù)據(jù)
     * 這一點(diǎn)EasyExcel有自己的解決方案
     *
     * 2.其次就是DB里插入,怎么去插入這20w條數(shù)據(jù)
     * 當(dāng)然不能一條一條循環(huán),應(yīng)該批量插入20w條數(shù)據(jù)
     * 同樣不能選擇Mybatis的批量插入,因?yàn)樾实?
     *
     * 3.使用JDBC+事務(wù)的批量操作將數(shù)據(jù)插入到數(shù)據(jù)庫
     * */
    //批量導(dǎo)入
    @PostMapping("/batchImportExcel")
    public void batchImportExcel(MultipartFile file) throws IOException {
        if (BeanUtil.isEmpty(file)){
            log.debug("傳入的文件不能為空!");
            return ;
        }
        if (!Objects.requireNonNull(file.getOriginalFilename()).endsWith("xls") && !file.getOriginalFilename().endsWith("xlsx")){
            log.debug("請(qǐng)上傳Excel文件!");
            return ;
        }
        CommonExportListenerDto commonExportListenerDto = new CommonExportListenerDto();
        EasyExcel.read(file.getInputStream(),commonExportListenerDto).doReadAll();
    }
}

3.Service層

@Service
@Slf4j
public class UserService {
//
    @Resource
    private IndMapper indMapper;
    //文件導(dǎo)出
    public void exportInspectionPlan(HttpServletRequest request, HttpServletResponse response) {
        //以上需要根據(jù)自己的業(yè)務(wù)去做數(shù)據(jù)處理   這里就不做展示
        try {
            //給文件命名
            String fileName = "ExcelTest";
            // 設(shè)置響應(yīng)頭
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("UTF-8");
            // 設(shè)置防止中文名亂碼
            fileName = URLEncoder.encode(fileName, "utf-8");
            // 文件下載方式(附件下載還是在當(dāng)前瀏覽器打開)
            response.setHeader("Content-disposition", "attachment;filename=" +
                    fileName + ".xlsx");
            //向excel表格寫入數(shù)據(jù)
            EasyExcel.write(response.getOutputStream(), ExportPlanInformationVo.class)
                    .sheet("下方導(dǎo)航")
                    .doWrite(getAll());
/*
            //下載到指定路徑
            String fileUrl = "D://ExcelTest.xlsx";
            //向excel表格寫入數(shù)據(jù)
            EasyExcel.write(fileUrl, ExportPlanInformationVo.class)
                    .sheet("下方導(dǎo)航")
                    .doWrite(getAll());
*/
        } catch (Exception e) {
            log.error("出現(xiàn)錯(cuò)誤 {}", e);
        }
    }
 
    public List<ExportPlanInformationVo> getAll(){
        //根據(jù)業(yè)務(wù)邏輯獲取數(shù)據(jù)
//        List<ExportPlanInformationVo> all = indMapper.getAll();
        return  indMapper.getAll();
    }
 
}

4.Utils工具類

import java.sql.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
 
public class JDBCUtil {
 
    private static String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false";
    private static String username = "root";
    private static String password = "196713";
    private static String driverName = "com.mysql.jdbc.Driver";
 
    /**
     * 獲取連接對(duì)象
     *
     * @return 連接對(duì)象
     */
    public static Connection getConnection() {
        Connection conn = null;
        try {
            // 1. 注冊(cè)驅(qū)動(dòng)
            Class.forName(driverName);
            // 2. 獲取連接對(duì)象
            conn = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return conn;
    }
 
 
    /**
     * 釋放資源
     *
     * @param connection 連接對(duì)象
     * @param statement  預(yù)編譯執(zhí)行對(duì)象
     * @param resultSet  結(jié)果集
     */
    public static void releaseResources(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        // 釋放資源
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
 
    public static void insertBatch(List<Map<Object, Object>> dataList, String sql) {
        Connection conn = null;
        PreparedStatement pstm = null;
        try {
            conn = getConnection();
            //如果需要開啟事務(wù)此處需要將自動(dòng)提交關(guān)閉
            // conn.setAutoCommit(false);
            //預(yù)編譯sql
            pstm = (PreparedStatement) conn.prepareStatement(sql);
            for (Map<Object, Object> map : dataList) {
                //此處類型判斷不完整后續(xù)可以借鑒jdk自行封裝攔截器
                for (int i = 1; i <= map.size(); i++) {
                    Object o = map.get(i-1);
                    if (BeanUtil.isEmpty(o)) {
                        pstm.setString(i, null);
                        continue;
                    }
                    if (o instanceof String) {
                        pstm.setString(i, o.toString());
                        continue;
                    }
                    if (o instanceof Integer) {
                        pstm.setInt(i, Integer.parseInt(o.toString()));
                        continue;
                    }
                    if (o instanceof LocalDateTime) {
                        pstm.setDate(i, new Date(System.currentTimeMillis()));
                        continue;
                    }
                    if (o instanceof Boolean) {
                        pstm.setBoolean(i, Boolean.parseBoolean(o.toString()));
                    }
                }
                //添加到同一個(gè)批處理中
                pstm.addBatch();
            }
            //執(zhí)行批處理
            pstm.executeBatch();
            //如果需要開啟事務(wù)此處需要手動(dòng)提交事務(wù)
            //conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
 
}

5.自定義監(jiān)聽器

@Data
@Slf4j
public class CommonExportListenerDto extends AnalysisEventListener<Map<Object, Object>> {
 
    /**
     * 表頭數(shù)據(jù)(存儲(chǔ)所有的表頭數(shù)據(jù))
     */
    private List<Map<Integer, String>> headList = new ArrayList<>();
 
    /*
     * 數(shù)據(jù)體
     */
    private List<Map<Object, Object>> dataList = new ArrayList<>();
 
    /**
     * 存儲(chǔ)全部表頭數(shù)據(jù)
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        headList.add(headMap);
    }
 
    /**
     * 每一條數(shù)據(jù)解析都會(huì)來調(diào)用
     * @param data
     * @param context
     */
    @Override
    public void invoke(Map<Object, Object> data, AnalysisContext context) {
        dataList.add(data);
        if (dataList.size() >= 3) {
            saveData();
            // 存儲(chǔ)完成清理 list
            dataList = ListUtils.newArrayListWithExpectedSize(2000);
        }
    }
 
    /**
     * 所有數(shù)據(jù)解析完成之后的操作
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();
    }
 
    private void saveData() {
        log.info("{}條數(shù)據(jù),開始存儲(chǔ)數(shù)據(jù)庫!", dataList.size());
        //批量導(dǎo)入
        JDBCUtil.insertBatch(dataList,"INSERT INTO ind (a,b,c,d,e) VALUES(?,?,?,?,?);");
        log.info("存儲(chǔ)數(shù)據(jù)庫成功!");
    }
}

6.實(shí)體類

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@HeadRowHeight(value = 30) // 頭部行高
@ContentRowHeight(value = 25) // 內(nèi)容行高
@ColumnWidth(value = 20) // 列寬
@HeadFontStyle(fontName = "宋體", fontHeightInPoints = 11)
public class ExportPlanInformationVo  implements Serializable {
 
// 1. 如果不想某個(gè)字段在excel中出現(xiàn)  可以加  @ExcelIgnore注解
    @ExcelProperty(value = "a")
    private String a;
 
 
//    @Dict(code = "inspectionType", fieldName = "inspectionTypeName")
    @ExcelProperty(value = "b")
    private String b;
 
    @ExcelProperty(value = "c")
    private String c;
    @ExcelProperty(value = "d")
    private String d;
    @ExcelProperty(value = "c")
    private String e;
 
 
}

7.Mapper層

@Mapper
public interface IndMapper {
 
    @Select("select * from ind")
    List<ExportPlanInformationVo> getAll();
 
}

以上就是SpringBoot整合EasyExcel實(shí)現(xiàn)批量導(dǎo)入導(dǎo)出的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot EasyExcel導(dǎo)入導(dǎo)出的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java?C++題解leetcode902最大為N的數(shù)字組合數(shù)位DP

    Java?C++題解leetcode902最大為N的數(shù)字組合數(shù)位DP

    這篇文章主要為大家介紹了Java?C++題解leetcode902最大為N的數(shù)字組合數(shù)位DP,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • kafka運(yùn)維consumer-groups.sh消費(fèi)者組管理

    kafka運(yùn)維consumer-groups.sh消費(fèi)者組管理

    這篇文章主要為大家介紹了kafka運(yùn)維consumer-groups.sh消費(fèi)者組管理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • IDEA強(qiáng)制清除Maven緩存的方法示例

    IDEA強(qiáng)制清除Maven緩存的方法示例

    這篇文章主要介紹了IDEA強(qiáng)制清除Maven緩存的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 基于GeoTools和SpringBoot的省域駕車最快路線規(guī)劃方法

    基于GeoTools和SpringBoot的省域駕車最快路線規(guī)劃方法

    本文探討基于GeoTools與SpringBoot的省域駕車最快路線規(guī)劃方法,解決復(fù)雜路況與地理因素影響,通過天地圖API計(jì)算并存儲(chǔ)距離數(shù)據(jù),展示湖南、新疆、黑龍江等地的路線成果,為交通與經(jīng)濟(jì)影響評(píng)估提供參考,感興趣的朋友快來一起學(xué)習(xí)吧
    2025-07-07
  • Java中處理日期時(shí)間的幾種操作技巧

    Java中處理日期時(shí)間的幾種操作技巧

    日期和時(shí)間是幾乎所有應(yīng)用程序中都會(huì)遇到的問題,從簡單的顯示當(dāng)前時(shí)間,到復(fù)雜的日期計(jì)算和時(shí)區(qū)處理,日期時(shí)間操作是開發(fā)中不可避免的一部分,Java提供了不同的工具來幫助我們處理日期和時(shí)間,本文為大家詳細(xì)說說,需要的朋友可以參考下
    2026-01-01
  • java數(shù)據(jù)結(jié)構(gòu)與算法之快速排序詳解

    java數(shù)據(jù)結(jié)構(gòu)與算法之快速排序詳解

    這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之快速排序,結(jié)合實(shí)例形式詳細(xì)分析了快速排序的原理、實(shí)現(xiàn)步驟、相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2017-05-05
  • 微服務(wù)Spring?Boot?整合Redis?阻塞隊(duì)列實(shí)現(xiàn)異步秒殺下單思路詳解

    微服務(wù)Spring?Boot?整合Redis?阻塞隊(duì)列實(shí)現(xiàn)異步秒殺下單思路詳解

    這篇文章主要介紹了微服務(wù)Spring?Boot?整合Redis?阻塞隊(duì)列實(shí)現(xiàn)異步秒殺下單,使用阻塞隊(duì)列實(shí)現(xiàn)秒殺的優(yōu)化,采用異步秒殺完成下單的優(yōu)化,本文給大家分享詳細(xì)步驟及實(shí)現(xiàn)思路,需要的朋友可以參考下
    2022-10-10
  • SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案

    SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案

    這篇文章主要給大家介紹了關(guān)于SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案的相關(guān)資料,包括數(shù)據(jù)加密方案、解密傳輸數(shù)據(jù)實(shí)現(xiàn)方案和響應(yīng)數(shù)據(jù)加密實(shí)現(xiàn)方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • Java連接MySQL數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)交互的示例

    Java連接MySQL數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)交互的示例

    數(shù)據(jù)庫是非常重要的一種存儲(chǔ)格式,可以大大提高存儲(chǔ)效率,本文主要介紹了Java連接MySQL數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)交互的示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • java利用Apache commons codec進(jìn)行MD5加密,BASE64加密解密,執(zhí)行系統(tǒng)命令

    java利用Apache commons codec進(jìn)行MD5加密,BASE64加密解密,執(zhí)行系統(tǒng)命令

    這篇文章主要介紹了java利用apache Commons包進(jìn)行MD5加密,BASE64加密解密與執(zhí)行系統(tǒng)命令希望對(duì)大家有用
    2017-12-12

最新評(píng)論

庐江县| 尼勒克县| 平陆县| 邯郸市| 栾城县| 修水县| 呼伦贝尔市| 汾阳市| 三穗县| 华坪县| 宁陕县| 恩平市| 丹凤县| 高雄县| 壤塘县| 南乐县| 黔东| 怀集县| 临江市| 彩票| 富锦市| 疏勒县| 成安县| 莱阳市| 大关县| 壶关县| 蕲春县| 昭觉县| 开平市| 涟源市| 武平县| 昔阳县| 千阳县| 石景山区| 天峻县| 神农架林区| 康马县| 南宁市| 晋城| 志丹县| 宁化县|