Spring-Batch之HelloWorld

Spring-Batch之HelloWorld程序

Springbatch的一些基础理论知识请参考其他的博客或者相关书籍。在这里我就不阐述了,我留一下实战经验分享给大家吧,在实战的过程中可能会引用一些基础知识。

目录


实战介绍

本实战案例如下图所示:
需要插入500万条假数据到 Oralce数据库中的Student表中。

思路介绍

Spring-Batch的处理分为三个阶段,第一个阶段为reader,第二阶段为processor,第三阶段为writer,这样的写法其实规定的比较死板,而且我试验过三者缺一不可,如果我们用自定义的tasklet就体会不到架构的好处了。所以在这里我的思路如下
1. reader阶段组装假数据并生成Student对象(使用自定义方法)
2. processor自定义方法
3. writer复写JdbcBatchItemWriter将数据插入数据库中(因为有可能insert语句会因为一些情况外界自动生成的,顺便说一下里面一些方法的执行顺序)

xml核心配置如下:

    <job id="insertData">
        <step id="dbWirterStep">
            <tasklet transaction-manager="transactionManager">
                <chunk reader="restarCustomStudentItemReader" 
                 processor="partTranslateProcessor" 
                 writer="jdbcSetterItemWriter" 
                 commit-interval="4000"></chunk>
            </tasklet>
        </step>
    </job>
    <!-- 插入数据库中 这里需要注意的是我将JdbcBatchItemWriter进行了复写,这样可以更加灵活的控制SQL,不用将其写死在配置文件中 -->
     <bean:bean id="jdbcSetterItemWriter" 
        class="springbatch.MyJdbcBatchItemWriter">
        <bean:property name="dataSource" ref="dataSource"/>
<!--         <bean:property name="sql" ref=" insert into Student(NAME,SEX,BIRTH,AGE,ORIGIN,REMARKS) values(?,?,?,?,?,?)"/> -->
        <bean:property name="itemPreparedStatementSetter">
            <bean:bean class="springbatch.DestCreditBillItemPreparedStatementSetter"/>
        </bean:property>
    </bean:bean>
     <!-- 自定义类用于生成假数据 -->
    <bean:bean id="restarCustomStudentItemReader" class="springbatch.RestartableCustomStudentItemReader">
        <bean:property name="currentLocation" value="5000000"></bean:property>
    </bean:bean>
    <!-- 处理程序 -->
    <bean:bean id="partTranslateProcessor" class="springbatch.PartTranslateItemProcessor"/>

下来是Java程序如下RestartableCustomStudentItemReader.java

package springbatch;

import java.util.Date;
import java.util.Map;

import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;

import pojo.Student;
import utils.RandomNameUtils;

/**
 * @author xiaohunding
 */
public class RestartableCustomStudentItemReader implements ItemReader<Student>{
    private int currentLocation = 0;
    private int count = 0;

    public RestartableCustomStudentItemReader() {
        super();
        System.out.println("我只插入一次");
    }
    /**
     * 制作假数据
     */
    public Student read() throws Exception, UnexpectedInputException,
            ParseException, NonTransientResourceException {
         Student student = new Student();
         if(count<currentLocation) {//当count超过5000000时停止输出
             Map<String,String> map = RandomNameUtils.getAddress();//随机生成测试数据(请参考源码)
             student = new Student("id",map.get("name").toString(),Short.parseShort("1"),new Date(),Short.parseShort("24"),"lala",map.get("road").toString());
             count++;
             if (count%1000==1) {
                 System.out.println("我读了:"+count+":"+student);
            }
             return student;
         }
         System.out.println("我读了:"+count+":"+student);
         return null;
    }

    public int getCurrentLocation() {
        return currentLocation;
    }

    public void setCurrentLocation(int currentLocation) {
        this.currentLocation = currentLocation;
    } 

}

PartTranslateItemProcessor.java处理如下:


package springbatch;

import org.springframework.batch.item.ItemProcessor;

import pojo.Student;

/**
 * 
 * @author xiaohunding
 */
public class PartTranslateItemProcessor implements
        ItemProcessor<Student, Student> {
    //做一些转化数据,处理数据和验证数据等操作
    public Student process(Student bill) throws Exception {
        //bill.setAddress(bill.getAddress() + "," + bill.getName());
        System.out.println("进入数据转化");
        return bill;
    }
}

MyJdbcBatchItemWriter.java处理如下:

package springbatch;

import java.util.List;

import org.springframework.batch.item.database.JdbcBatchItemWriter;

public class MyJdbcBatchItemWriter<T> extends JdbcBatchItemWriter<T>{

    private String STUDENT_SQL = "insert into Student(NAME,SEX,BIRTH,AGE,ORIGIN,REMARKS) values(?,?,?,?,?,?)";
    @Override
    public void setSql(String sql) {
        super.setSql(sql);
    }

    @Override
    public void afterPropertiesSet() {
        setSql(STUDENT_SQL);
        super.afterPropertiesSet();
    }
    /**
     * 动态获取
     */
    @Override
    public void write(List<? extends T> items) throws Exception {
        super.write(items);
    }
}

在这里有人会问,JdbcBatchItemWriter这个类已经很强大了为什么要复写它呢,原因是SQL语句在一些时候是会跟随业务的不一样而发生变化的,所以复写它就是想让SQL语句更加的灵活起来我可以这样写(如下)

    @Override
    public void setSql(String sql) {
        Connection conn = null;
        ResultSet rs = null;
        try {
            conn = getDataSource().getConnection();
            Statement st = conn.createStatement();
            rs = st.executeQuery(sql);//执行sql语句并返回结果集
            StringBuffer sb = new StringBuffer();
            while (rs.next()) {
                String name=rs.getString("NAME");
                sb.append(name+",");
            }
            sb.deleteCharAt(sb.length()-1);
            sql = "select "+ sb.toString()+" FROM STUDENT";
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                rs.close();
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        super.setSql(sql);
    }

这样SQL语句就是从数据库中动态组装的了。以此类推,其他的方法也可以这样重写一下即可达到效果但是请初始化在afterPropertiesSet()方法里面。

    @Override
    public void afterPropertiesSet() throws Exception {
    //从数据库中将元数据获取到并动态生成SQL语句
        final Map<String, Object> map = <<...从数据库通过元数据和各种业务方法生成的SQL语句...>>

        //动态生成SQL语句
        super.setSql(map.get("KINGBASE_SQL").toString());
        //动态绑定参数
        super.setRowMapper(new RowMapper(){

            public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                Map<String, Object> dataMap = new ListOrderedMap();
                List<String> list = (List<String>)map.get("FIELDNAME");
                for (String fieldName : list) {
                    dataMap.put(fieldName,rs.getObject(fieldName));
                }   
                return dataMap;
            }
        }); 

        super.afterPropertiesSet();
    }

“<<>>”此处为伪代码

核心代码就这些了。下一篇:我们来进一步实战,从一个数据库中将数据导入到另外一个数据库中.请关注。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值