利用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();
        }
    }
}
posted @ 2021-10-06 23:26  JaxYoun  阅读(1989)  评论(0编辑  收藏  举报