我在生产中有一个Spring Batch部署,它最初是使用作业存储库的H2数据源开发的。这项初步工作一切正常,但我们希望用更传统的数据库替换H2,因为我们使用Spring Batch进行扩展。无论好坏(这不完全是我的决定),我转而使用MySQL。
我已将作业存储库的数据源从H2切换到MySQL,并将元素更改为使用“classpath:/org/springframework/batch/core/schema-mysql.sql
”。当我第一次运行批处理作业时,Spring Batch会创建存储库表并毫无问题地运行我的作业。
然而,后续执行失败...即使我正在使用作业增量器,传递“-next
”参数,并且看到它与H2一起工作正常。当我将日志记录设置为“调试”级别时,我看到后续执行时会出现以下异常:
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)];
Duplicate entry '1' for key 'PRIMARY';
nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
我查看了Spring Batch用于创建其作业存储库表的“schema-*.sql
”脚本。其他数据库类型(例如H2,Oracle,Postgres等)创建三个序列...... BATCH_STEP_EXECUTION_SEQ
,BATCH_JOB_EXECUTION_SEQ
和BATCH_JOB_SEQ
。我不是MySQL专家,但看起来MySQL缺乏对序列的支持......因为“schema-mysql.sql
”包含这些行作为一个明显的解决方法:
CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM;
INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0);
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM;
INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0);
CREATE TABLE BATCH_JOB_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM;
INSERT INTO BATCH_JOB_SEQ values(0);
很明显,MySQL对序列和自动增量值的处理与其他数据库不同,因此假设Spring Batch必须做一些不同的事情来增加其作业存储库表中的ID。我需要采取其他一些特定于MySQL的步骤,我可能不知道吗?提前致谢!
答案 0 :(得分:1)
问题是我在每个作业运行时都在执行classpath:/org/springframework/batch/core/schema-mysql.sql
脚本。
使用H2,这很好......只要jdbc:initialize-database
元素包含ignore-failures="ALL"
属性,您就不会发现问题。
但是,对于序列的特定于MySQL的解决方法并不是可以在没有Spring Batch搞砸的情况下重复执行的。
我从Spring Batch配置中删除了jdbc:initialize-database
元素,在空数据库中手动执行了classpath:/org/springframework/batch/core/schema-mysql.sql
安装脚本一次,我的作业运行了多次调用就好了。