Spring Batch "Nom d'objet invalide BATCH_JOB_INSTANCE"

Sep 27 2020

J'ai créé un lot de printemps pour interroger une base de données de serveur Azure SQL et écrire les données dans un fichier CSV. Je n'ai pas les createautorisations pour la base de données. J'obtiens cette erreur Invalid Object name BATCH_JOB_INSTANCElors de l'exécution du lot. Je ne veux pas que les tables de méta-données Spring batch soient créées dans la base de données principale. Ou il serait utile que je puisse les avoir dans une autre base de données locale ou en mémoire comme h2db. J'ai également spring-batch-initialize-schema=neverdéjà ajouté , ce qui était le cas avec la plupart des réponses à des questions similaires ici, mais cela n'a pas aidé.

Éditer:

J'ai résolu l' Invalid Object nameerreur en empêchant les tables de métadonnées d'être créées dans la base de données principale en étendant la DefaultBatchConfigurerclasse et en remplaçant la setDataSourceméthode, les faisant ainsi créées dans le référentiel de cartes en mémoire. Maintenant, je veux essayer deux options:

  1. Comment créer les tables de métadonnées dans une base de données locale ou une base de données en mémoire comme h2db.
  2. Ou si les tables de métadonnées sont déjà créées dans la base de données principale, dans un schéma différent de ma table principale à partir de laquelle je récupère. Comment pointer mon travail vers ces tables de métadonnées dans un autre schéma, pour stocker les données du travail et des détails d'étape dans celles-ci.
@Configuration
public class SpringBatchConfig extends DefaultBatchConfigurer{

@Override
    public void setDataSource(DataSource datasource) {

    }
...

Mon fichier application.properties ressemble à ceci:

spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

spring-batch-initialize-schema=never
spring.batch.job.enabled=false

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect

Réponses

MahmoudBenHassine Oct 02 2020 at 07:57

Comment créer les tables de métadonnées dans une base de données locale ou une base de données en mémoire comme h2db.

Vous pouvez utiliser spring.batch.initialize-schema=embeddedpour cela.

Ou si les tables de métadonnées sont déjà créées dans la base de données principale, dans un schéma différent de ma table principale à partir de laquelle je récupère. Comment pointer mon travail vers ces tables de métadonnées dans un autre schéma, pour stocker les données du travail et des détails d'étape dans celles-ci.

spring batch fonctionne avec une source de données, pas un schéma particulier. Si les tables de métadonnées se trouvent dans un schéma différent, vous devez créer une seconde source de données pointant vers ce schéma et la définir sur le référentiel de travaux.

JosephXu Oct 09 2020 at 06:45

J'ai créé une démo avec deux sources de données. Les métadonnées Batch seront stockées dans H2 DB et la source de données Job est Azure SQL.

Voici la structure du projet:

  1. Nous devons définir une DataSourceConfigclasse et utiliser l' @Primaryannotation pour le bean DataSource:
@Configuration
public class DataSourceConfig {

    @Bean(name = "mssqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource appDataSource(){
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name = "h2DataSource")
    @Primary
    // @ConfigurationProperties(prefix="spring.datasource.h2")
    public DataSource h2DataSource() {
        return DataSourceBuilder.create()
                .url("jdbc:h2:mem:thing:H2;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE")
                .driverClassName("org.h2.Driver")
                .username("sa")
                .password("")                   
                .build();
    }
    
}
  1. Dans la classe ItemReaderDbDemo, nous utilisons @Autowired @Qualifier("mssqlDataSource")pour spécifier la source de données dans la tâche Spring Batch:
@Configuration
public class ItemReaderDbDemo {
    
    //generate task Object
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    
    //Step exec tasks
    //generate step Object
    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    @Qualifier("mssqlDataSource")
    private DataSource dataSource;

    @Autowired
    @Qualifier("dbJdbcWriter")
    private ItemWriter<? super Todo> dbJdbcWriter;
    
    @Bean
    public Job itemReaderDbDemoJob() {
        return jobBuilderFactory.get("itemReaderDbDemoJob").start(itemReaderDbStep()).build();
    }

    @Bean
    public Step itemReaderDbStep() {
        return stepBuilderFactory.get("itemReaderDbStep")
                .<Todo,Todo>chunk(2)
                .reader(dbJdbcReader())
                .writer(dbJdbcWriter)
                .build();
    }

    @Bean
    @StepScope
    public JdbcPagingItemReader<Todo> dbJdbcReader() {
        JdbcPagingItemReader<Todo> reader = new JdbcPagingItemReader<Todo>();
        reader.setDataSource(dataSource);
        reader.setFetchSize(2);
        reader.setRowMapper(new  RowMapper<Todo>() {
            @Override
            public Todo mapRow(ResultSet rs, int rowNum) throws SQLException {
                Todo todo = new Todo();
                todo.setId(rs.getLong(1));
                todo.setDescription(rs.getString(2));
                todo.setDetails(rs.getString(3));
                return todo;
            }   
            
        });
        SqlServerPagingQueryProvider provider = new  SqlServerPagingQueryProvider();
        provider.setSelectClause("id,description,details");
        provider.setFromClause("from dbo.todo");
        
        //sort
        Map<String,Order> sort = new HashMap<>(1);
        sort.put("id", Order.DESCENDING);
        provider.setSortKeys(sort);
        
        reader.setQueryProvider(provider);
        return reader;
    }
}

  1. Voici mon application.properties:
logging.level.org.springframework.jdbc.core=DEBUG

spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.jdbcUrl=jdbc:sqlserver://josephserver2.database.windows.net:1433;database=<Your-Database-Name>;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
spring.datasource.username=<Your-UserName>
spring.datasource.password=<Your-Password>
spring.datasource.initialization-mode=always
  1. Il renvoie le résultat attendu de mon Azure SQL. À propos, mon nom d'utilisateur Azure SQL ne dispose pas des autorisations de création pour la base de données.
    Le résultat montre: