Spring Batch “Ungültiger Objektname BATCH_JOB_INSTANCE”
Ich habe einen Spring Batch erstellt, um eine Azure SQL Server-Datenbank abzufragen und die Daten in eine CSV-Datei zu schreiben. Ich habe keine createBerechtigungen für die Datenbank. Ich erhalte diesen Fehler Invalid Object name BATCH_JOB_INSTANCEbeim Ausführen des Stapels. Ich möchte nicht, dass die Spring-Batch-Metadatentabellen in der Hauptdatenbank erstellt werden. Oder es wäre hilfreich, wenn ich sie in einer anderen lokalen oder speicherinternen Datenbank wie h2db haben könnte. Ich habe auch spring-batch-initialize-schema=neverbereits hinzugefügt , was bei den meisten Antworten auf ähnliche Fragen hier der Fall war, aber das hat nicht geholfen.
Bearbeiten:
Ich habe den Invalid Object nameFehler behoben , indem verhindert wurde, dass die Metadatentabellen in der Hauptdatenbank erstellt werden, indem die DefaultBatchConfigurerKlasse erweitert und die setDataSourceMethode überschrieben wurde , sodass sie im speicherinternen Map-Repository erstellt wurden. Jetzt möchte ich zwei Optionen ausprobieren:
- So erstellen Sie die Metadatentabellen in einer lokalen Datenbank oder einer speicherinternen Datenbank wie h2db.
- Oder Wenn ich die Metadatentabellen bereits in der Hauptdatenbank erstellt habe, in einem anderen Schema als meiner Haupttabelle, aus der ich abrufe. Wie ich meinen Job auf diese Metadatentabellen in einem anderen Schema verweise, um die Job- und Schrittdetaildaten in diesen zu speichern.
@Configuration
public class SpringBatchConfig extends DefaultBatchConfigurer{
@Override
public void setDataSource(DataSource datasource) {
}
...
Meine Datei application.properties sieht folgendermaßen aus:
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
Antworten
So erstellen Sie die Metadatentabellen in einer lokalen Datenbank oder einer speicherinternen Datenbank wie h2db.
Sie können dafür verwenden spring.batch.initialize-schema=embedded.
Oder Wenn ich die Metadatentabellen bereits in der Hauptdatenbank erstellt habe, in einem anderen Schema als meiner Haupttabelle, aus der ich abrufe. Wie ich meinen Job auf diese Metadatentabellen in einem anderen Schema verweise, um die Job- und Schrittdetaildaten in diesen zu speichern.
Spring Batch arbeitet mit einer Datenquelle, nicht mit einem bestimmten Schema. Wenn sich Metadatentabellen in einem anderen Schema befinden, müssen Sie eine zweite Datenquelle erstellen, die auf dieses Schema verweist, und diese im Job-Repository festlegen.
Ich habe eine Demo mit zwei Datenquellen erstellt. Stapelmetadaten werden in H2 DB gespeichert, und die Jobdatenquelle ist Azure SQL.
Hier ist die Projektstruktur:
- Wir müssen eine
DataSourceConfigKlasse definieren und@PrimaryAnnotation für DataSource Bean verwenden:
@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();
}
}
- In der ItemReaderDbDemo-Klasse geben wir
@Autowired @Qualifier("mssqlDataSource")die dataSource in der Spring Batch-Task an:
@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;
}
}
- Hier ist meine 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
- Es gibt das erwartete Ergebnis von meinem Azure SQL zurück. Mein Azure SQL-Benutzername verfügt übrigens nicht über Erstellungsberechtigungen für die Datenbank.
Das Ergebnis zeigt: