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();
}
}
}