1. 程式人生 > >資料處理---Spring Batch之實踐

資料處理---Spring Batch之實踐

上面介紹了Spring Batch的基本概念和簡單的demo專案,顯然這些還是不夠實際使用的。下面我們來更多的程式碼實踐。

        在上面的基礎專案上面,我們來更多的修改:

        不用專案預設的hsql DB,用mysql,讓ItemReader,ItemWriter 支援mysql;

        支援處理結果自定義儲存到資料庫,我們用專案裡面的JPA;

        讓Quartz來定時呼叫spring batch的Job

        可以讀取檔案,而不只是資料庫;

下面開始動手。

          修改pom.xml,節選部分,實在太長了。

          <spring.framework.version>3.2.0.RELEASE</spring.framework.version>
          <spring.batch.version>2.1.7.RELEASE</spring.batch.version>   <!--  這個的版本和quartz的版本要注意,不然很容易在執行的時候出錯 -->

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.23</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.3.2.RELEASE.rebuild</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.10.Final</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.1.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>

launch-context.xml定義需要用到的bean,

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="spring" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect">
    <bean class="com.test.batch.CustomHibernateJpaDialect" />
  </property>
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/testbatch?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="customerMapper" class="com.test.batch.CustomerMapper"></bean>
<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"></bean>
        <!--   這個可以讓spring batch和hibernate共用
<bean id="itemReader"
class="org.springframework.batch.item.database.HibernateCursorItemReader">
<property name="sessionFactory" ref="sessionFactory" />
<property name="queryString" value="from CustomerCredit" />
</bean>
-->
<bean id="itemReaderFile" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="lineTokenizer"/>
<property name="fieldSetMapper" ref="customerMapper"/>
</bean>   
</property>
<!--<property name="resource" value="file:#{jobParameters['customFileAbPath']}"/>   配置讀取檔案的路徑,我固定了       -->
<property name="resource" value="file:D:/temp/testdata.txt"/>
</bean>
<bean id="itemReader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
    <property name="dataSource" ref="dataSource"/>
    <property name="sql" value="select ID, NAME, CREDIT from CUSTOMER"/>
    <property name="rowMapper">
        <bean class="com.test.batch.CustomerCreditRowMapper"/>
    </property>
    <property name="fetchSize" value="100"></property>
    <property name="maxRows" value="10000"></property>
</bean>

<jdbc:initialize-database data-source="dataSource">
<!-- <jdbc:script location="${batch.schema.script}" /> -->
<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />
</jdbc:initialize-database

<!-- batch:job-repository id="jobRepository" / -->
<batch:job-repository id="jobRepository"
data-source="dataSource" transaction-manager="transactionManager"
isolation-level-for-create="SERIALIZABLE" table-prefix="BATCH_" />
        <!-- 下面是Quartz呼叫spring batch 的job要用到的 -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list><ref bean="scheduledTrigger"></ref></list>
</property>
</bean>

<bean id="scheduledTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="jobDetail"/>
   <property name="cronExpression">
        <value>*/10 * * * * ?</value>
    </property>
</bean>

<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.test.batch.JobLauncherDetails" />
<property name="jobDataAsMap">
<map>
<entry key="jobName" value="job1" />  <!--指定jobID -->
<entry key="jobLocator" value-ref="jobRegistry" />
<entry key="jobLauncher" value-ref="jobLauncher" />
<entry key="param1" value="p1" />
<entry key="param2" value="p2" />
</map>
</property>
<property name="durability" value="true" />
</bean>

        <bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
  </bean>

  <bean
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry" />
       </bean>

       <bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />

<import resource="classpath:/META-INF/spring/module-context.xml" />

有幾個定製的東西,需要說下。

我們用到的domain物件是這樣的,很多不必要的都省略了

@Entity
@Table(name = "customer")
public class CustomerCredit {
public static final String TABLE_NAME = "customer";

@Column(name = "name", nullable = true, length = 12)
private String name;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;

@Column(name = "credit", nullable = true, precision = 15, scale = 2)
private BigDecimal credit;

FlatFileItemReader 使用預設的DefaultLineMapper,裡面指定了lineTokenizer和fieldSetMapper,就是說要怎麼讀一行行的資料,讀了之後怎麼和Bean的欄位Mapper,這樣後面的步驟好繼續處理。

public class CustomerMapper implements FieldSetMapper<CustomerCredit> {
@Override
public CustomerCredit mapFieldSet(FieldSet fieldSet) throws BindException {
CustomerCredit lv = new CustomerCredit();
lv.setId(Integer.parseInt(fieldSet.readString(0)));
lv.setName(fieldSet.readString(1));
lv.setCredit(fieldSet.readBigDecimal(2));
return lv;
}
}

如果是讀資料庫呢?就是下面那個JdbcCursorItemReader,裡面指定了dataSource,sql,rowMapper,這些都類似檔案

public class CustomerCreditRowMapper implements RowMapper {
    public static final String ID_COLUMN = "id";
    public static final String NAME_COLUMN = "name";
    public static final String CREDIT_COLUMN = "credit";

    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
        CustomerCredit customerCredit = new CustomerCredit();
        customerCredit.setId(rs.getInt(ID_COLUMN));
        customerCredit.setName(rs.getString(NAME_COLUMN));
        customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN));
        return customerCredit;
    }
}

還可以和hibernate結合來讀取資料,可以讀取儲存過程的資料,等等,具體可以參考spring batch文件

說好的自定義處理資料呢,比如我們把每個人的Credit加10.

@Component("customProcessor")
public class CustomProcessor implements
ItemProcessor<CustomerCredit, CustomerCredit> {
@PersistenceContext
private EntityManager em;
@Override
public CustomerCredit process(CustomerCredit item) throws Exception {
System.out.println(new Date().toString()+"start to process");
if (item == null) {
return null;
}
try {
item = em.find(CustomerCredit.class, item.getId());
item.setCredit(item.getCredit().add(new BigDecimal(10)));
//find by id才可以persist (否則出現detached entity passed to persist)
em.persist(item);
} catch (Exception e) {
e.printStackTrace();
}
return item;
}
}

每一步的處理,我們想看看結果,可以定製一個ItemReadListener

public class CustomStepListener implements ItemReadListener<CustomerCredit>   具體程式碼省略

修改module-context.xml

<batch:job id="job1">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager"
start-limit="100">
<batch:chunk reader="itemReade" writer="itemwriter" processor="customProcessor" 
commit-interval="3" />
</batch:tasklet>
</batch:step>
</batch:job>

在META-INF下面加個persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="spring" transaction-type="RESOURCE_LOCAL">
<!-- 
<class>com.test.jpatest.model.Customer</class>
<class>com.test.jpatest.model.Address</class>
-->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
</persistence-unit>
</persistence>

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exampleConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.batch.core.repository.JobRepository com.test.batch.ExampleConfiguration.jobRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [launch-context.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [launch-context.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No persistence unit with name 'spring' found

執行的時候遇到上面的錯誤,就是沒有上面的配置的原因

org.springframework.transaction.InvalidIsolationLevelException: Standard JPA does not support custom isolation levels - use a special JpaDialect for your JPA implementation
at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:66)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:59)

遇到這樣的錯誤,是因為預設的JPA不支援自定義的事物隔離級別。可以自定義一個CustomHibernateJpaDialect extends HibernateJpaDialect,具體程式碼沒有列出,可以找下。

在用Quartz的時候遇到

Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class  

這個是由於網上的很多例子都是quartz版本稍舊的原因,我用的是quartz 2.1.7

錯誤:Jobs added with no trigger must be durable
<property name="durability" value="true" />  

坑真的是不少,需要一個個解決。最後測試一下,是不是定時執行我們的job:

public class App {
public static void main(String[] args) {
String springConfig = "launch-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(
springConfig);
}
}

祝你好運,能夠成功,微笑

相關推薦

資料處理---Spring Batch實踐

上面介紹了Spring Batch的基本概念和簡單的demo專案,顯然這些還是不夠實際使用的。下面我們來更多的程式碼實踐。         在上面的基礎專案上面,我們來更多的修改:         不用專案預設的hsql DB,用mysql,讓ItemReader,Item

資料處理---Spring Batch基礎

      Spring框架提供了強大的底層結構,基於此,Spring出現了很多方面的應用。Spring Batch就是其一,它是一個輕量級的,完全面向Spring的批處理框架,可以應用於企業級大量的資料處理系統。Spring Batch以POJO和大家熟知的Spring框

資料處理-Spring Batch Scaling and Parallel Processing

承蒙各位擡愛,鄙人的一篇關於Spring Batch的部落格《Spring Batch之進階》有很多人瀏覽。說明有很多人工作中用到這個spring batch框架進行批量任務處理,也說明對這個框架還有不少不熟悉的地方,鄙人也是。That is to say,我們

資料共享-spring batch(9)上下文處理

[TOC] > 在 Spring Batch 中進行資料及引數傳遞的方法。 ## 1 引言 本文是 Spring Batch 系列文章的第9篇,有興趣的可見文章: - [資料批處理神器-Spring Batch(1)簡介及使用場景](https://mp.weixin.qq.com/s/mH0k

Spring Batch flow 介紹和使用

         通過前文我們已經知道,Step 是一個獨立的、順序的處理步驟,包含完整的輸入、處理以及輸出。但是在企業應用中,我們面對的更多情況是多個步驟按照一定的順序進行處理。因此如何維護步驟之間的執行順序是我們需要考慮的。Spring Ba

Spring Batch Job的建立和呼叫

     在上一篇文章  Spring Batch 之 背景框架簡介   中,已經概述了Batch的基本架構組織,並且運行了簡易demo。 在接下來的篇幅中,將逐步介紹每個元件的使用方式,並結合業務進行批處理。  

Spring Batch 背景框架簡介

            Spring Batch 是一個輕量級的、全面的批處理框架,用於開發對企業系統的日常操作至關重要的健壯批處理應用程式。Spring  Batch提供了處理大量記錄所必需的可重用功能,包括日誌/跟蹤、

核磁資料處理: FSL系列flirt命令

flirt 是FSL的線性修正工具. 官方提供了非常豐富的呼叫方式: - 命令Flirt可以啟動FLIRT的GUI + InvertXFM, ApplyXFM, ConcatXFM - 命令flirt 是命令列工具 - misc flirt util

spring batch三 配置和執行Job

4.6.3. JobOperator  sping batch 提供了JobOperator對batch 操作進行重啟,總結,停止操作. public interface JobOperator { List<Long> getExecutions(long instanceI

核磁資料處理: FSL系列segmentation工具FAST

fsl的segmentation工具: FAST (FMRIB’s Automated Segmentation Tool)將大腦組織的3D影響分解為不同的組織,比如灰質\白質\腦脊液等等, 同時還可以進行spatial intensity variations

python 資料處理學習pandasDataFrame(三)

請原諒沒有一次寫完,本文是自己學習過程中的記錄,完善pandas的學習知識,對於現有網上資料的缺少和利用python進行資料分析這本書部分知識的過時,只好以記錄的形勢來寫這篇文章.最如果後續工作定下來有時間一定完善pandas庫的學習,請見諒!               

spring batch二 一個簡單的spring batch的例子.

在實際工作中我們可能需要快速的實現一個spring batch.本文作為一個參考例子。 主要使用maven ,STS tool.   spring.framework.version 3.0.6.RELEASE. spring.batch.version 2.1.7.REL

Spring batch 操作資料庫

common.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://

史上最輕鬆入門Spring Batch - 輕量級批處理框架實踐

從 MariaDB 一張表內讀 10 萬條記錄,經處理後寫到 MongoDB 。 Batch 任務模型 具體實現 1、新建 Spring Boot 應用,依賴如下: <!-- Web 應用 --> <dependency> <group

Spring Boot Spring Batch處理實踐

#### 實踐內容 從 MariaDB 一張表內讀 10 萬條記錄,經處理後寫到 MongoDB 。 #### 具體實現 1、新建 Spring Boot 應用,依賴如下: ```xml

Spring Batch:將資料從Web服務處理到MongoDB

概觀 在這篇文章中,我們將介紹如何建立一個使用Web服務資料並將其插入MongoDB資料庫的Spring Batch應用程式。 要求 閱讀本文的開發人員必須熟悉Spring Batch(示例)和MongoDB。 環境 Mongo資料庫部署在MLab中。請按照本快速入門中的步驟操作。 批

薦書丨深度學習美——AI時代的資料處理與最佳實踐

點選上方“程式人生”,選擇“置頂公眾號”第一時間關注程式猿(媛)身邊的故事零入門 | 高可讀|

資料處理框架Spring Batch 的全面解析

如今微服務架構討論的如火如荼。但在企業架構裡除了大量的OLTP交易外,還存在海量的批處理交易。在諸如銀行的金融機構中,每天有3-4萬筆的批處理作業需要處理。針對OLTP,業界有大量的開源框架、優秀的架構設計給予支撐;但批處理領域的框架確鳳毛麟角。是時候和我們一起來了解下批處理的世界哪些優秀的框架和設計了,今天

大量資料也不在話下,Spring Batch並行處理四種模式初探

# 1 前言 > 歡迎訪問[南瓜慢說 www.pkslow.com](https://www.pkslow.com/)獲取更多精彩文章! `Spring相關文章:`[Springboot-Cloud](https://www.pkslow.com/categories/springboot) 前

Spring Security應用開發(11) 並發控制實踐

nag line then 9.png page 總結 -c ole for 本文分別介紹了四種不同情況下,Spring Security的Session管理和並發控制的不同配置的配置方法,以及所產生的效果。 (1)首先編寫了session_error.jsp頁面,用於