Using Spring Batch with auto-configure and a non-standard database

我与影子孤独终老i 提交于 2019-12-02 15:03:16

问题


I am attempting to create a Spring Batch application. We use a SQL Anywhere database, which is effectively SQLSERVER, a known database type. To make things easier I am using @SpringBootApplication on my main class and @EnableBatchProcessing on my configuration class.

The problem is that my database driver, sybase.jdbc4.sqlanywhere.IDriver, returns a product name "SQL Anywhere" and this is not recognized by Spring, causing various errors. I was able to get past some of them by explicitly creating a JobRepositoryFactoryBean in my configuration class:

/**
 * We can't rely on Spring Boot as it can't set the database type properly.
 * 
 * By explicitly requiring the arguments in the constructor, we force the Autowiring
 * to occur.
 */
@Bean
public JobRepositoryFactoryBean jobRepositoryFactory(DataSource ds, PlatformTransactionManager tm) {
    JobRepositoryFactoryBean jf = new JobRepositoryFactoryBean();

    jf.setDataSource(ds);
    jf.setTransactionManager(tm);
    jf.setDatabaseType("SQLSERVER");
    jf.setTablePrefix("DBA.BATCH_");
    jf.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");    // only one instance at a time

    return jf;
}

However, DefaultBatchConfigurer fails in the intialize function, because it explicitly constructs its own JobExplorerFactoryBean.

I wonder if there is some simple way around this, or if I will have to duplicate the work in the DefaultBatchConfigurer class and define all the beans myself and remove the @EnableBatchProcessing annotation.


回答1:


I was able to solve this, and I hope it helps anyone trying to use Spring Batch with a database that is out-of-the-box. It is necessary to extend DefaultBatchConfigurer and override the createJobRepository() function. Also, you should disable the automatic job table creation.

Here is the class I created that can be used as a base for any SQL Anywhere Spring Batch job:

@EnableBatchProcessing
public class SqlAnywhereBatchConfigurer extends DefaultBatchConfigurer {

  @Autowired
  private DataSource dataSource;
  @Autowired
  private PlatformTransactionManager transactionManager;

  public SqlAnywhereBatchConfigurer() {
      super();
  }

  public SqlAnywhereBatchConfigurer(DataSource dataSource) {
      super(dataSource);
  }

  @Override
  protected JobRepository createJobRepository() throws Exception {
    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(dataSource);
    factory.setTransactionManager(transactionManager);
    factory.setDatabaseType("SQLSERVER");
    factory.afterPropertiesSet();
    return factory.getObject();
  }
}

Remember to use the schema-sqlserver.sql to set up your tables first.

You must define a datasource in your configuration, in application.properties I have:

# database
spring.datasource.url=jdbc:sqlanywhere:Server=<your server name>;port=2638
spring.datasource.username=<your username>
spring.datasource.password=<your password>
spring.datasource.driver-class-name=sybase.jdbc4.sqlanywhere.IDriver
# don't create tables on startup
spring.datasource.initialize=false
spring.batch.initializer.enabled=false

Finally, it is worth mentioning here that for SQL Anywhere at least the JdbcCursorItemReader does not work, because setting the fetch direction of the prepared statement causes a "not supported" SQL Exception to be thrown. You can get around this by extending JdbcCursorItemReader and overriding the applyStatementSettings function (plus a few setters) in your own class.



来源:https://stackoverflow.com/questions/43241229/using-spring-batch-with-auto-configure-and-a-non-standard-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!