Help us understand the problem. What is going on with this article?

【Spring Batch】JobRepositoryへの保存時にカラムのサイズを超えてしまう

More than 3 years have passed since last update.

Spring Batchをいじっている最中に遭遇した問題です。

環境

Spring Boot 1.3.2.RELEASE
spring-boot-starter-batch
SQL Server 2012

エラー

発生のタイミングは、Job実行中に例外が発生してJobが中断されるときでした。

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]; 文字列データまたはバイナリ データが切り捨てられます。; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 文字列データまたはバイナリ データが切り捨てられます。
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:102) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ...

原因はBATCH_STEP_EXECUTION. EXIT_MESSAGEにカラムサイズを超える値をセットしようとしたことでした。
EXIT_MESSAGEのカラム定義はvarchar(2500)です。
さて、SQL Server 2012の場合、文字列型のサイズの数え方は下記の通りとなります。

数え方
charおよびvarchar バイト数
ncharおよびnvarchar 文字数

JobRepositoryへのINSERTおよびUPDATEでは、カラム定義を考慮してバッチ処理のなかで2500文字以上の文字は切り捨てられます。
上記のUPDATE文では、EXIT_MESSAGEにスタックトレースを入れようとしていたのですが、スタックトレースに日本語等のマルチバイト文字が含まれていました。
そうなると挿入文字数は2500文字以内に収まっているのに、バイト数に換算すると2500バイトを超えてしまうというわけでした。

回避方法

カラムの型をnvarcharに変更する

JobRepositoryのテーブルが生成されるたびに変えなくてはいけないので面倒ですが。。。
更新するのは

  • BATCH_JOB_EXECUTION.EXIT_MESSAGE
  • BATCH_STEP_EXECUTION.EXIT_MESSAGE

の2つです。

文字数の上限を2500から減らす

こっちはコードで回避できます。

BatchConfiguration.java
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

    @Bean
    public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager manager) throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setMaxVarCharLength(2000);
        factory.setDataSource(dataSource);
        factory.setTransactionManager(manager);
        return factory.getObject();
    }

    ...
    (後略)
    ...

}

JobRepositoryFactoryBean#setMaxVarCharLength を使って、文字数の上限を2500から減らせば、バイト数でカウントしても収まるという計算です。
ですが、マルチバイト文字が多いとやっぱり駄目です。。。

カラムのサイズを増やす

文字数の上限を変えるのと同じ発想です。varchar(2500)からvarchar(3000)くらいにすれば収まる気がします。

余談

ISSUEがあったのですが、「上手いやり方がないから手動でなんとかしてくれ」(超訳)とのことです。

参考

https://sites.google.com/site/soracane/home/springnitsuite/spring-batch/7-spring-batchno-tips#TOC-JobRepository-
https://jira.spring.io/browse/BATCH-1296

shindo_ryo
Java / JavaScript / TypeScript / Spring Framework
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした