2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?