Spring Batch "Nome oggetto non valido BATCH_JOB_INSTANCE"
Ho creato un batch primaverile per interrogare un database del server SQL di Azure e scrivere i dati in un file CSV. Non ho le createautorizzazioni per il database. Ottengo questo errore Invalid Object name BATCH_JOB_INSTANCEdurante l'esecuzione del batch. Non voglio che le tabelle dei metadati del batch primaverile vengano create nel database principale. Oppure sarebbe utile se posso averli in un altro db locale o in memoria come h2db. Ho anche spring-batch-initialize-schema=nevergià aggiunto , che era il caso con la maggior parte delle risposte a domande simili qui, ma ciò non ha aiutato.
Modificare:
Ho risolto l' Invalid Object nameerrore impedendo la creazione delle tabelle di metadati nel database principale estendendo la DefaultBatchConfigurerclasse e sovrascrivendo il setDataSourcemetodo, facendole così creare nel repository di mappe in memoria. Ora voglio provare due opzioni:
- Come creare le tabelle dei metadati in un database locale o in memoria come h2db.
- Oppure, se ho le tabelle dei metadati già create nel database principale, in uno schema diverso dalla tabella principale da cui sto recuperando. Come indirizzare il mio lavoro a quelle tabelle di metadati in un altro schema, per memorizzare i dati del lavoro e dei dettagli del passaggio in essi.
@Configuration
public class SpringBatchConfig extends DefaultBatchConfigurer{
@Override
public void setDataSource(DataSource datasource) {
}
...
Il mio file application.properties ha questo aspetto:
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
Risposte
Come creare le tabelle dei metadati in un database locale o in memoria come h2db.
Puoi usare spring.batch.initialize-schema=embeddedper quello.
Oppure, se ho le tabelle dei metadati già create nel database principale, in uno schema diverso dalla tabella principale da cui sto recuperando. Come indirizzare il mio lavoro a quelle tabelle di metadati in un altro schema, per memorizzare i dati del lavoro e dei dettagli del passaggio in essi.
Spring batch funziona su un'origine dati, non su uno schema particolare. Se le tabelle dei metadati si trovano in uno schema diverso, è necessario creare una seconda origine dati che punta a quello schema e impostarla sul repository del lavoro.
Ho creato una demo con due origini dati. I metadati batch verranno visualizzati in H2 DB e l'origine dati del lavoro è Azure SQL.
Ecco la struttura del progetto:
- È necessario definire una
DataSourceConfigclasse e utilizzare l'@Primaryannotazione per il 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();
}
}
- Nella classe ItemReaderDbDemo, usiamo
@Autowired @Qualifier("mssqlDataSource")per specificare dataSource nell'attività 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;
}
}
- Ecco la mia 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
- Restituisce il risultato atteso dal mio Azure SQL. A proposito, il mio nome utente Azure sql non dispone delle autorizzazioni di creazione per il database.
Il risultato mostra: