Spring batch sample 之 text to DB

Spring batch sample 之 text to DB
例子很简单:
txt文件如下:
[code]
sampleSource.txt
kinaei,30
zoubin,40
ZHUTOU,65
wufeiran,51
[/code]

需要存放到一张表中:
[code]
CREATE MEMORY TABLE BATCH_TEST(NAME VARCHAR(20) NOT NULL PRIMARY KEY,AGE BIGINT)
[/code]
利用sts自带的spring-batch的模板生成样板代码。自己完成的无非是reader 和 writer两块。
下面是主要的配置代码:
[code]
<?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:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<description>Example job to get you started. It provides a
skeleton for a typical batch application.</description>

<job id="job1" xmlns="http://www.springframework.org/schema/batch">
<step id="step1" parent="simpleStep">
<tasklet>
<chunk reader="reader" writer="writer"/>
</tasklet>
</step>
</job>

<!--
<bean id="reader" class="org.springframework.sample.batch.example.ExampleItemReader">
<property name="sampleFile" value="classpath:sampleSource.txt" />
</bean>
-->
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:sampleSource.txt" />
<property name="lineMapper" >
<bean id="defaultLineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names">
<list>
<value>name</value>
<value>age</value>
</list>
</property>
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="testbean" />
</bean>
</property>

</bean>
</property>
</bean>

<bean id="testbean" class="org.springframework.sample.batch.example.TestBean" scope="prototype"/>


<bean id="writer" class="org.springframework.sample.batch.example.ExampleItemWriter" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="simpleStep"
class="org.springframework.batch.core.step.item.SimpleStepFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="jobRepository" ref="jobRepository" />
<property name="startLimit" value="100" />
<property name="commitInterval" value="1" />
</bean>


</beans>
[/code]

主要的工作就是把需要读取的文件是一个逗号分割的文件,先把每一行转换为一个bean然后交给writer去写入数据库。
首先来看一下reader,Spring提供的基础设施及其完善,几乎不用写任何代码就能把一个reader配置完成了。一个reader主要由两部分组成:
【1】resource 告诉reader从哪里去读文件
[code]<property name="resource" value="classpath:sampleSource.txt" />[/code]
【2】lineMapper 就是说txt文件中的每一行映射成怎样的一个bean。
如何把文件的一行映射成为一个bean呢?
【A】需要知道分割符号式什么,在spring 中就叫做:lineTokenizer。可能的话还要提供每个字段对应的名称。
[code]
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names">
<list>
<value>name</value>
<value>age</value>
</list>
</property>
</bean>
</property>
[/code]
这里告诉系统用逗号分隔符,并且第一字段叫name,第二个字段叫age
【B】需要把txt文件中的字段映射到bean中的对应字段中并且做好字段的类型转换工作。Spring中就叫做fieldSetMapper
[code]
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="testbean" />
</bean>
</property>
[/code]
这里用到了spring的基础设施,即BeanWrapperFieldSetMapper它会根据txt文件读出的字段与给定的bean进行同名装配,自动的映射成了一个bean叫做testbean。
【C】 testbean 是什么的 定义如下
[code]
<bean id="testbean" class="org.springframework.sample.batch.example.TestBean" scope="prototype"/>

package org.springframework.sample.batch.example;

import java.io.Serializable;

public class TestBean implements Serializable{
private String name;
private Integer age;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
[/code]

这样reader就写好了。

剩下的就是writer了,由于spring没有提供方面的Database ItemWriters只能自己写了。
[code]
package org.springframework.sample.batch.example;

import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.ItemWriter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;


/**
* Dummy {@link ItemWriter} which only logs data it receives.
*/
public class ExampleItemWriter implements ItemWriter<Object> {

private static final Log log = LogFactory.getLog(ExampleItemWriter.class);

private DataSource dataSource;

public DataSource getDataSource() {
return dataSource;
}

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

/**
* @see ItemWriter#write(Object)
*/
public void write(List<? extends Object> data) throws Exception {
TestBean rs=null;
for(Object line : data){
rs=(TestBean)line; //actual just one
}

final Object[] params=new Object[2];
params[0]=rs.getName();
params[1]=rs.getAge();
System.out.println(ToStringBuilder.reflectionToString(rs));


TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus arg0) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("insert into BATCH_TEST(NAME,AGE) VALUES(?,?)",params);
return null;
}
});

}

}

[/code]

配置如下:
[code]
<bean id="writer" class="org.springframework.sample.batch.example.ExampleItemWriter" >
<property name="dataSource" ref="dataSource" />
</bean>
[/code]

最后谈一下总体的感觉:
【1】代码简单清晰许多,只需要把精力放在reader和writer的代码中。其他的如出错处理等都有spring代劳了。
【2】自动装配的这个reader用起来非常方便。
【3】自动实现了有状态的读取。为了防止读写过程中突然出错,在启动的时候重复读,或者漏读。以前读文件的时候要么是先把整个文件读写完毕后再commit,既浪费应用服务器的内存,又影响db的性能。要么要再写个文件记录读取的条数,重启后先判断读取的位置,在接着做。现在SPRING的这个reader自动提供了(当然代价是建立了记录状态的spring_batch的一系列的表),非常方便。
【4】在写writer的时候有spring来管理connection的事务提交。原来自己写的时候需要把connection传来传去以保证事务的完整性。比如如果要实现读两行再一次提交的话,可能connect 会贯穿于reader和writer或者再写个类去管理这个connection这里都提交给了spring。

实践下来我的结论是如果你要写一个读取文件,再做相应的处理后写入数据库的程序的话利用spring-batch绝对物有所值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值