spring Batch实现数据库大数据量读写
1. data-source-context.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
- <!-- 1) USE ANNOTATIONS TO IDENTIFY AND WIRE SPRING BEANS. -->
- <context:component-scan base-package="net.etongbao.vasp.ac" />
- <!-- 2) DATASOURCE, TRANSACTION MANAGER AND JDBC TEMPLATE -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
- destroy-method="close" abstract="false" scope="singleton">
- <!-- oracle.jdbc.driver.oracleDriver -->
- <property name="driverClass" value="oracle.jdbc.OracleDriver" />
- <property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.1.23:1521:orcl01" />
- <property name="user" value="USR_DEV01" />
- <property name="password" value="2AF0829C" />
- <property name="checkoutTimeout" value="30000" />
- <property name="maxIdleTime" value="120" />
- <property name="maxPoolSize" value="100" />
- <property name="minPoolSize" value="2" />
- <property name="initialPoolSize" value="2" />
- <property name="maxStatements" value="0" />
- <property name="maxStatementsPerConnection" value="0" />
- <property name="idleConnectionTestPeriod" value="30" />
- </bean>
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource" ref="dataSource" />
- </bean>
- <bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
- <tx:annotation-driven transaction-manager="transactionManager" />
- </beans>
2. quartz-context.xml commit-interval="10000"每次批量数据的条数,数值越大效率越高,可在此处添加事物处理,
每次回滚数就是commit-interval数
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:batch="http://www.springframework.org/schema/batch"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
- <import resource="data-source-context.xml"/>
- <!-- JOB REPOSITORY - WE USE IN-MEMORY REPOSITORY FOR OUR EXAMPLE -->
- <bean id="jobRepository"
- class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
- <property name="transactionManager" ref="transactionManager" />
- </bean>
- <!-- batch config -->
- <bean id="jobLauncher"
- class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
- <property name="jobRepository" ref="jobRepository" />
- </bean>
- <!-- FINALLY OUR JOB DEFINITION. THIS IS A 1 STEP JOB -->
- <batch:job id="ledgerJob">
- <batch:listeners>
- <batch:listener ref="appJobExecutionListener" />
- </batch:listeners>
- <batch:step id="step1">
- <span style="white-space: pre;"> </span> <batch:tasklet transaction-manager="transactionManager">
- <batch:tasklet>
- <batch:listeners>
- <batch:listener ref="itemFailureLoggerListener" />
- </batch:listeners>
- <batch:chunk reader="ledgerReader" writer="ledgerWriter"
- commit-interval="10000" /> <!-- 1万条进行一次commit -->
- </batch:tasklet>
- </batch:tasklet>
- </batch:step>
- </batch:job>
- <!-- READER -->
- <bean id="ledgerReader"
- class="org.springframework.batch.item.database.JdbcCursorItemReader">
- <property name="dataSource" ref="dataSource" />
- <property name="sql" value="select * from ledger" />
- <property name="rowMapper" ref="ledgerRowMapper" />
- </bean>
- <!-- Spring Batch Job同一个job instance,成功执行后是不允许重新执行的【失败后是否允许重跑,可通过配置Job的restartable参数来控制,默认是true】,如果需要重新执行,可以变通处理,
- 添加一个JobParameters构建类,以当前时间作为参数,保证其他参数相同的情况下却是不同的job instance -->
- <bean id="jobParameterBulider" class="org.springframework.batch.core.JobParametersBuilder" />
- <!-- 定时任务 开始 -->
- <bean id="ledgerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
- <property name="targetObject">
- <!-- 定时执行的类 -->
- <ref bean="quartzLedgerJob" />
- </property>
- <property name="targetMethod">
- <!-- 定时执行的类方法 -->
- <value>execute</value>
- </property>
- </bean>
- <bean id="ledgerCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >
- <!-- 这里不可以直接在属性jobDetail中引用taskJob,因为他要求的是一个jobDetail类型的对象,所以我们得通过MethodInvokingJobDetailFactoryBean来转一下 -->
- <property name="jobDetail" >
- <ref bean="ledgerJobDetail" />
- </property>
- <!--在每天下午18点到下午18:59期间的每1分钟触发 -->
- <!--在每天上午10点40分准时触发 -->
- <property name="cronExpression" >
- <!-- <value>0 * 15 * * ?</value> -->
- <value>0 45 10 * * ? * </value>
- </property>
- </bean>
- <!-- 触发器工厂,将所有的定时任务都注入工厂-->
- <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <!-- 添加触发器 -->
- <property name="triggers">
- <list>
- <!-- 将上面定义的测试定时任务注入(可以定义多个定时任务,同时注入)-->
- <ref local="ledgerCronTrigger" />
- </list>
- </property>
- </bean>
- <!-- 定时任务 结束 -->
- lt;/beans>
3.定时调度job类 QuartzLedgerJob.java
package net.etongbao.vasp.ac.quartz;
- import java.util.Date;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.batch.core.Job;
- import org.springframework.batch.core.JobParametersBuilder;
- import org.springframework.batch.core.launch.JobLauncher;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StopWatch;
- /**
- * 定时调度类
- * @author Fu Wei
- *
- */
- @Component("quartzLedgerJob")
- public class QuartzLedgerJob {
- private static final Logger LOG = LoggerFactory.getLogger(QuartzLedgerJob.class);
- @Autowired
- private JobLauncher jobLauncher;
- @Autowired
- private Job ledgerJob;
- @Autowired
- JobParametersBuilder jobParameterBulider;
- private static long counter = 0l;
- /**
- * 执行业务方法
- * @throws Exception
- */
- public void execute() throws Exception {
- LOG.debug("start...");
- StopWatch sw = new StopWatch();
- sw.start();
- /*
- * Spring Batch Job同一个job instance,成功执行后是不允许重新执行的【失败后是否允许重跑,
- * 可通过配置Job的restartable参数来控制,默认是true】,如果需要重新执行,可以变通处理,
- * 添加一个JobParameters构建类,以当前时间作为参数,保证其他参数相同的情况下却是不同的job instance
- */
- jobParameterBulider.addDate("date", new Date());
- jobLauncher.run(ledgerJob, jobParameterBulider.toJobParameters());
- sw.stop();
- LOG.debug("Time elapsed:{},Execute quartz ledgerJob:{}", sw.prettyPrint(), ++counter);
- }
- }
4.程序启动类 StartQuartz.java
package net.etongbao.vasp.ac.quartz;
- import java.io.FileNotFoundException;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * 启动定时调度
- * @author Fu Wei
- *
- */
- public class StartQuartz {
- public static void main(String[] args) throws FileNotFoundException {
- new ClassPathXmlApplicationContext("/net/etongbao/vasp/ac/resources/quartz-context.xml");
- }
- }
5.pojo类 Ledger.java
- package net.etongbao.vasp.ac.pojo;
- import java.io.Serializable;
- import java.util.Date;
- public class Ledger implements Serializable {
- private int id;
- private Date receiptDate;
- private String memberName;
- private String checkNumber;
- private Date checkDate;
- private String paymentType;
- private double depositAmount;
- private double paymentAmount;
- private String comments;
- public Ledger() {
- super();
- }
- public Ledger(int id, Date receiptDate, String memberName, String checkNumber, Date checkDate, String paymentType,
- double depositAmount, double paymentAmount, String comments) {
- super();
- this.id = id;
- this.receiptDate = receiptDate;
- this.memberName = memberName;
- this.checkNumber = checkNumber;
- this.checkDate = checkDate;
- this.paymentType = paymentType;
- this.depositAmount = depositAmount;
- this.paymentAmount = paymentAmount;
- this.comments = comments;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public Date getReceiptDate() {
- return receiptDate;
- }
- public void setReceiptDate(Date receiptDate) {
- this.receiptDate = receiptDate;
- }
- public String getMemberName() {
- return memberName;
- }
- public void setMemberName(String memberName) {
- this.memberName = memberName;
- }
- public String getCheckNumber() {
- return checkNumber;
- }
- public void setCheckNumber(String checkNumber) {
- this.checkNumber = checkNumber;
- }
- public Date getCheckDate() {
- return checkDate;
- }
- public void setCheckDate(Date checkDate) {
- this.checkDate = checkDate;
- }
- public String getPaymentType() {
- return paymentType;
- }
- public void setPaymentType(String paymentType) {
- this.paymentType = paymentType;
- }
- public double getDepositAmount() {
- return depositAmount;
- }
- public void setDepositAmount(double depositAmount) {
- this.depositAmount = depositAmount;
- }
- public double getPaymentAmount() {
- return paymentAmount;
- }
- public void setPaymentAmount(double paymentAmount) {
- this.paymentAmount = paymentAmount;
- }
- public String getComments() {
- return comments;
- }
- public void setComments(String comments) {
- this.comments = comments;
- }
- }
6. LedgerDaoImpl.java
package net.etongbao.vasp.ac.dao.impl;
- import java.sql.PreparedStatement;
- import java.sql.SQLException;
- import net.etongbao.vasp.ac.dao.LedgerDao;
- import net.etongbao.vasp.ac.pojo.Ledger;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.PreparedStatementSetter;
- import org.springframework.stereotype.Repository;
- /**
- * ledger数据操作类
- *
- * @author Fu Wei
- *
- */
- @Repository
- public class LedgerDaoImpl implements LedgerDao {
- private static final String SAVE_SQL = "insert into ledger_temp (rcv_dt, mbr_nm, chk_nbr, chk_dt, pymt_typ, dpst_amt, pymt_amt, comments) values(?,?,?,?,?,?,?,?)";
- @Autowired
- private JdbcTemplate jdbcTemplate;
- @Override
- public void save(final Ledger item) {
- jdbcTemplate.update(SAVE_SQL, new PreparedStatementSetter() {
- public void setValues(PreparedStatement stmt) throws SQLException {
- stmt.setDate(1, new java.sql.Date(item.getReceiptDate().getTime()));
- stmt.setString(2, item.getMemberName());
- stmt.setString(3, item.getCheckNumber());
- stmt.setDate(4, new java.sql.Date(item.getCheckDate().getTime()));
- stmt.setString(5, item.getPaymentType());
- stmt.setDouble(6, item.getDepositAmount());
- stmt.setDouble(7, item.getPaymentAmount());
- stmt.setString(8, item.getComments());
- }
- });
- }
- }
7.接口 LedgerDao .java
- package net.etongbao.vasp.ac.dao;
- import net.etongbao.vasp.ac.pojo.Ledger;
- public interface LedgerDao {
- public void save(final Ledger item) ;
- }
8. JdbcTemplete 需要的LedgerRowMapper.java
package net.etongbao.vasp.ac.batch.writer;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import net.etongbao.vasp.ac.pojo.Ledger;
- import org.springframework.jdbc.core.RowMapper;
- import org.springframework.stereotype.Component;
- /**
- * ledger行的映射类
- * @author Administrator
- *
- */
- @Component("ledgerRowMapper")
- public class LedgerRowMapper implements RowMapper {
- public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
- Ledger ledger = new Ledger();
- ledger.setId(rs.getInt("id"));
- ledger.setReceiptDate(rs.getDate("rcv_dt"));
- ledger.setMemberName(rs.getString("mbr_nm"));
- ledger.setCheckNumber(rs.getString("chk_nbr"));
- ledger.setCheckDate(rs.getDate("chk_dt"));
- ledger.setPaymentType(rs.getString("pymt_typ"));
- ledger.setDepositAmount(rs.getDouble("dpst_amt"));
- ledger.setPaymentAmount(rs.getDouble("pymt_amt"));
- ledger.setComments(rs.getString("comments"));
- return ledger;
- }
- }
9.关键类LedgerWriter.java ,写入数据,负责数据的添加
- package net.etongbao.vasp.ac.batch.writer;
- import java.util.List;
- import net.etongbao.vasp.ac.dao.LedgerDao;
- import net.etongbao.vasp.ac.pojo.Ledger;
- import org.springframework.batch.item.ItemWriter;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- /**
- * ledger写入数据
- *
- * @author Fu Wei
- *
- */
- @Component("ledgerWriter")
- public class LedgerWriter implements ItemWriter<Ledger> {
- @Autowired
- private LedgerDao ledgerDao;
- /**
- * 写入数据
- *
- * @param ledgers
- */
- public void write(List<? extends Ledger> ledgers) throws Exception {
- for (Ledger ledger : ledgers) {
- ledgerDao.save(ledger);
- }
- }
- }
classPath:
<?xml version="1.0" encoding="UTF-8"?>
- <classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jrockit-jdk1.6.0_24-R28.1.3-4.0.1"/>
- <classpathentry kind="lib" path="lib/aopalliance-1.0.jar"/>
- <classpathentry kind="lib" path="lib/c3p0-0.9.1.2.jar"/>
- <classpathentry kind="lib" path="lib/commons-collections-3.2.1.jar"/>
- <classpathentry kind="lib" path="lib/commons-lang-2.3.jar"/>
- <classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
- <classpathentry kind="lib" path="lib/etb-log4j-1.2.16.jar"/>
- <classpathentry kind="lib" path="lib/etb-slf4j-api-1.5.8.jar"/>
- <classpathentry kind="lib" path="lib/etb-slf4j-log4j12-1.5.8.jar"/>
- <classpathentry kind="lib" path="lib/ojdbc6.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.aop-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.asm-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.aspects-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.beans-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.context-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.context.support-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.core-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.expression-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.instrument-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.jdbc-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.jms-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.orm-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.oxm-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.test-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/org.springframework.transaction-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/quartz-all-1.6.5.jar"/>
- <classpathentry kind="lib" path="lib/spring-batch-core-2.1.6.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/spring-batch-infrastructure-2.1.6.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/spring-batch-test-2.1.6.RELEASE.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
- <classpathentry kind="output" path="bin"/>
- </classpath>
总结: 测试数据8万多条,响应时间3分多钟。
关键在于quartz-context.xml 中<bean id="ledgerReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select * from ledger" />
<property name="rowMapper" ref="ledgerRowMapper" />
</bean> 负责读取数据 ,在程序执行时一次性抓取全部数据后在批量的交给LedgerWriter进行写操作。当然也可以使用分页读取JdbcPagingItemReader,但要分页数量与写入数量要大写相同,还可以对分页出来的数据进行添加悲观锁
LedgerWriter.java 负责写入数据,每次写入1000条。
spring Batch实现数据库大数据量读写的更多相关文章
- kettle大数据量读写mysql性能优化
修改kettleDB连接设置 1. 增加批量写的速度:useServerPrepStmts=false rewriteBatchedStatements=true useCompressio ...
- 大数据量高并发的数据库优化详解(MSSQL)
转载自:http://www.jb51.net/article/71041.htm 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能. ...
- 大数据量数据库设计与优化方案(SQL优化)
转自:http://blog.sina.com.cn/s/blog_6c0541d50102wxen.html 一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的 ...
- 大数据量高并发的数据库优化,sql查询优化
一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...
- 大数据量查询优化——数据库设计、SQL语句、JAVA编码
数据库设计方面: 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将 ...
- MySQL数据库如何解决大数据量存储问题
利用MySQL数据库如何解决大数据量存储问题? 各位高手您们好,我最近接手公司里一个比较棘手的问题,关于如何利用MySQL存储大数据量的问题,主要是数据库中的两张历史数据表,一张模拟量历史数据和一张开 ...
- MYSQL数据库导入大数据量sql文件失败的解决方案
1.在讨论这个问题之前首先介绍一下什么是"大数据量sql文件". 导出sql文件.选择数据库-----右击选择"转储SQL文件"-----选择"结构和 ...
- POI读写大数据量excel,解决超过几万行而导致内存溢出的问题
1. Excel2003与Excel2007 两个版本的最大行数和列数不同,2003版最大行数是65536行,最大列数是256列,2007版及以后的版本最大行数是1048576行,最大列数是16384 ...
- 大数据量下的SQL Server数据库自身优化
原文: http://www.d1net.com/bigdata/news/284983.html 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情 ...
随机推荐
- 使用fastcgi部署django应用
1.fastcgi和cgi的区别 1)CGI (Common Gateway Interface): 用来作为 Web Server 同 Python, PHP 等的通信手段.而在静态网页的时代, 只 ...
- VUEJS2.0源码理解--优
VUEJS2.0源码理解 http://jiongks.name/blog/vue-code-review/#pingback-112428
- ubuntu刚安装好之后apt-get使用异常
gaozhang 刚安装好之后,想执行apt-get update 任务,出现以下错误提示 提示说明apt正在执行,我们就野蛮的将apt进程杀.死即可,不过有点多,一个个kill 执行完之后再 ...
- Java基础3一基础语句
1.条件语句:所谓的条件语句就是指有选择的去执行部分代码. 包括:if条件语句和switch条件语句 if条件语句: 语法: (1)if(条件语句){ //条件成立时需要执行的代码 } (2)if ...
- 第一课 导入库 - 创建数据集 - CSV读取 - 导出 - 查找最大值 - 绘制数据
第1课 创建数据 - 我们从创建自己的数据集开始分析.这可以防止阅读本教程的最终用户为得到下面的结果而不得不下载许多文件.我们将把这个数据集导出到一个文本文件中,这样您就可以获得从文本文件中一些拉取数 ...
- Windows Server2008上安装VS2008出错及解决办法
作者:朱金灿 来源:http://blog.csdn.net/clever101 win server 2008安装vs2008后报错,如下图: 然后到网上找了一种解决办法: (1)打开服务器管理器 ...
- 一个关于C++拷贝构造的bug
#include <iostream> using namespace std; class A { public: A(int a) {}; A(const A&) = defa ...
- CV与IP:基础,经典以及最近发展
原文链接:http://blog.csdn.net/dcraw/article/details/7617891 原文编写层层递进,逻辑清晰: 不过看这篇转载可以少点击鼠标:http://blog.cs ...
- (转)基于MVC4+EasyUI的Web开发框架经验总结(1)-利用jQuery Tags Input 插件显示选择记录
http://www.cnblogs.com/wuhuacong/p/3667703.html 最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开 ...
- js去除html标记
function ff(str) { var dd = str.replace(/<\/?.+?>/g, ""); var dds = dd.replace(/ /g, ...