質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Spring Batch

Spring Batchは、バッチ処理向けに定義されたオープンソースのフレームワーク。エンタープライズシステムで避けて通れないバッチ処理を可能にします。設定ファイルに別定義することで効率よく開発することがで可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

MyBatis

MyBatisはJavaや.NET Frameworkでなどで使用できる、SQL文や、ストアドプロシージャをオブジェクトと紐付けるO/Rマッピングフレームワークです。

Q&A

解決済

1回答

4180閲覧

分割コミットをする方法がわかりません

SystemAjisai

総合スコア174

Spring Batch

Spring Batchは、バッチ処理向けに定義されたオープンソースのフレームワーク。エンタープライズシステムで避けて通れないバッチ処理を可能にします。設定ファイルに別定義することで効率よく開発することがで可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

MyBatis

MyBatisはJavaや.NET Frameworkでなどで使用できる、SQL文や、ストアドプロシージャをオブジェクトと紐付けるO/Rマッピングフレームワークです。

0グッド

0クリップ

投稿2020/07/17 03:08

前提・実現したいこと

SpringBatchとMyBatisを使ってCSVをデータベースに登録するバッチを作成しています。
バッチはチャンクモデルで作成していて、以下のような構成になっています。

  1. ItemReader・・・アクティブテーブルを読む
  2. ItemProcessor・・・アクティブデータに登録されているパスのCSVを読む
  3. ItemWriter・・・CSVファイルの中身を登録する

1のアクティブテーブルは、他システムが登録しているもので、キー情報とCSVのファイルパスが登録されています。
ItemProcessorでそのファイルを読み込み、フォーマットを統一してListに詰めます。
ItemWriterでListを受取ってDBに登録します。

最初に調べた時に、StepBuilderFactoryにchunk(1000)など設定しておくと、1000件ずつコミットしてくれると理解しました。
が、実際に動かしてみて初めて、CSVファイルの中身の件数じゃなくて、Readerで取得されるデータの件数で制御されることに気づきました…。

どのようにしたら分割でコミットができるのでしょうか?

発生している問題・エラーメッセージ

org.springframework.dao.TransientDataAccessResourceException: batch.XXXMapper.insertBulk (batch index #1) failed. Cause: java.sql.tion: Packet for query is too large (5,636,232 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.

max_allowed_packetを変えたらいいよと言われてるのは分かるのですが、このファイルが最大という訳でもないので分割でコミットしたいと思ってます。

該当のソースコード

■Step

java

1 @Bean 2 public Step insertCsvStep( 3 ItemReader<Activity> reader, 4 ItemProcessor<Activity, List<XXXData>> processor, 5 ItemWriter<List<XXXData>> writer) { 6 return stepBuilderFactory.get("insertCsvStep") 7 .<Activity, List<XXXData>> chunk(1000) 8 .reader(reader) 9 .processor(processor) 10 .writer(writer) 11 .build(); 12 }

■ItemReader
※単純にデータを取ってくるだけなので省略(多くて10件ぐらい)

■ItemProcessor
※ファイルによって項目数が違うのでsplitで分割しながら読んでます

java

1 @Override 2 public List<XXXData> process(Activity activity) throws Exception { 3 BufferedReader br = null; 4 // ItemWriterに渡すリスト 5 List<XXXData> result = new ArrayList<XXXData>(); 6 try { 7 File f = new File(activity.getPath()); 8 br = new BufferedReader(new FileReader(f)); 9 10 String sLine; 11 while ((sLine = br.readLine()) != null) { 12 csv = sLine.split(",", 0); 13 14 XXXData data = new XXXData(); 15 : 16 (諸々の加工処理) 17 : 18 result.add(data); 19 } 20 } catch (Exception e) { 21 // 省略 22 } finally { 23 if(br != null) br.close(); 24 } 25 return result; 26 }

■ItemWriter

java

1 @Bean 2 public MyBatisBatchItemWriter<List<XXXData>> insertXXXData() { 3 return new MyBatisBatchItemWriterBuilder<List<XXXData>>() 4 .sqlSessionFactory(sqlSessionFactory) 5 .statementId("batch.infra.mapper.XXXDataMapper.insertBulk") 6 .build(); 7 }

■Mapper(xml)

xml

1 <insert id="insertBulk" parameterType="java.util.List"> 2 INSERT INTO xxx_data ( 3 system_id, 4 : 5 ) 6 VALUES 7 <foreach item="record" collection="list" separator=","> 8 ( 9 #{record.system_id,jdbcType=VARCHAR}, 10 : 11 ) 12 </foreach> 13 </insert>

試したこと

application.ymlで下記のように設定を追加してみましたが、同じでした。

yml

1mybatis: 2 executor-type: BATCH 3 configuration: 4 default-executor-type: BATCH

補足情報(FW/ツールのバージョンなど)

SpringBoot2.3.1(プロジェクト作成時にSpringBatchを選択)
Java 13

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

Taskletで書いてDefaultTransactionDefinitionを使ったら自由にコミットできました。
最初に参考したサイトに「ItemReaderもWriterもいらない処理はTaskletで書けます」と書いてあるのを見て、DBアクセスが無い処理=Taskletのことだと曲解してしまっていました。

java

1 int insertCounter = 0; 2 3 BufferedReader br = null; 4 File f = new File(path); 5 String sLine = ""; 6 7 DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition(); 8 txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 9 TransactionStatus txStatus = null; 10 try { 11 String[] csv = null; 12 br = new BufferedReader(new FileReader(f)); 13 while ((sLine = br.readLine()) != null) { 14 csv = sLine.split(",", 0); 15 // トランザクションの開始 16 if (insertCounter % 1000 == 0) { 17 txStatus = txManager.getTransaction(txDefinition); 18 } 19 XXXData data = new XXXData(); 20 : 21 (諸々の加工処理) 22 : 23 XXXDataMapper.insert(data); 24 insertCounter++; 25 26 // コミットサイズになったらコミット 27 if(insertCounter % 1000 == 0) { 28 txManager.commit(txStatus); 29 } 30 } 31 } catch(Exception e) { 32 log.error("Exception:::" + sLine); 33 if(txManager != null) { 34 txManager.rollback(txStatus); 35 } 36 throw e; 37 } finally { 38 if(br != null) { 39 br.close(); 40 } 41 if (txStatus != null && !txStatus.isCompleted()) { 42 // 最後のチャンクについて、トランザクションをコミットする 43 txManager.commit(txStatus); 44 } 45 }

投稿2020/07/20 23:35

SystemAjisai

総合スコア174

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問