利用Spring之NamedParameterJdbcTemplate批量插入和更新Oracle+Sequence


package com.resources.novelcoronavirus.service.impl.opt.dao;

import com.resources.novelcoronavirus.domain.XiYaoZhongChengYaoPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;

/**
 * @author yang
 * @date 2018/10/6 23:27
 * @description 
 * 1、為了效率:利用Spring之NamedParameterJdbcTemplate,批量插入和更新Oracle。
 * 2、主鍵:使用Sequence生成主鍵。
 * 3、事務控制:若在數據源層面關閉了自動提交功能,需要使用@Transactional注解,自動提交事務。
 *【
 * 五六萬的數據量:
 * 1.最初使用的時MyBatis的循環單條插入,慢得不可接受。
 * 2.后改為MyBatis的foreach + 批處理,由於在Oracle中不支持像MySQL那樣利用VALUES關鍵字做動態拼接,只能使用SELECT ... FROM DUAL;在字符串長度超過2000時,
 * 這個DUAL表會引發CLOB類型轉換異常,由於我們的數據字段多,且長度無法預估,處理起來很棘手。
 * 3.又尋找BEGEN...END + foreach的方式,效率仍然不如人意。
 * 4.上述方案歸根到底利用的都是SQL拼接,simple_statement,數據庫每次都要做檢查、解析、編譯等工作,效率不高。
 * 最后使用了jdbc的prepared_statement,來做批處理,語句會被DB編譯並緩存,數據到來時,就像調用預編譯函數一樣,只需將數據當參數傳給預編譯語句,
 * 即可執行,最為高效。
 * 當然使用的時Spring封裝過的NamedParameterJdbcTemplate,易用性更高
 *】
 */
@Slf4j
@Service
public class Kill implements XyzcyDao {

    private static final String BATCH_INSERT_SQL = 
		"INSERT INTO 
			APPGM.YB_XYZCY (
			ID,
			YLMLBM,
			YPSPM,
			TYMBH
		) VALUES (
			APPGM.SEQ_YB_XYZCY.NEXTVAL,  //利用Sequence生成主鍵
			:YLMLBM,
			:YPSPM, 
			:TYMBH)";

    @Resource
    private DataSource dataSource;

    @Override
    @Transactional(rollbackFor = Exception.class)  //注意事務控制
    public void batchInsert(List<XiYaoZhongChengYaoPO> list) {
        NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(this.dataSource));  //新框架支持模板的依賴注入
        try {
            long start = System.currentTimeMillis();
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray());
            namedParameterJdbcTemplate.batchUpdate(BATCH_INSERT_SQL, batch);
            long end = System.currentTimeMillis();
            log.error("--------------> {}", end - start);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final String BATCH_UPDATE_SQL = 
			"UPDATE
				APPGM.YB_XYZCY
                         SET
				YLMLBM = :YLMLBM,
				YPSPM = :YPSPM,
				TYMBH = :TYMBH,
				YPTYM = :YPTYM,
				HXMC = :HXMC,
				BM = :BM
			WHERE
				YLMLBM = :YLMLBM";  //更新條件

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdate(List<XiYaoZhongChengYaoPO> list) {
        NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(this.dataSource));
        try {
            long start = System.currentTimeMillis();
            SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list.toArray());
            namedParameterJdbcTemplate.batchUpdate(BATCH_UPDATE_SQL, batch);
            long end = System.currentTimeMillis();
            log.error("==========> {}", end - start);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM