【问题标题】:Spring Batch "Invalid object name BATCH_JOB_INSTANCE"Spring Batch“无效的对象名称BATCH_JOB_INSTANCE”
【发布时间】:2021-01-13 13:23:31
【问题描述】:

我创建了一个 spring 批处理来查询 Azure SQL 服务器数据库并将数据写入 CSV 文件。我没有数据库的create 权限。我在运行批处理时收到此错误Invalid Object name BATCH_JOB_INSTANCE。我不希望在主数据库中创建 spring 批处理元数据表。或者,如果我可以将它们放在另一个本地或内存数据库(如 h2db)中,那将会很有帮助。 我也已经添加了spring-batch-initialize-schema=never,对于类似问题的大多数答案都是如此,但这没有帮助。

编辑:

我解决了Invalid Object name 错误,方法是通过扩展DefaultBatchConfigurer 类并覆盖setDataSource 方法来阻止将元数据表创建到主数据库中,从而在内存中的映射存储库中创建它们。现在我想尝试两种选择:

  1. 如何在本地数据库或内存数据库(如 h2db)中创建元数据表。
  2. 或者,如果我已经在主数据库中创建了元数据表,则使用与我从中获取的主表不同的架构。如何将我的工作指向另一个架构中的那些元数据表,以在其中存储工作和步骤详细信息数据。
@Configuration
public class SpringBatchConfig extends DefaultBatchConfigurer{

@Override
    public void setDataSource(DataSource datasource) {

    }
...

我的 application.properties 文件如下所示:

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

【问题讨论】:

    标签: sql-server spring spring-boot hibernate spring-batch


    【解决方案1】:

    我创建了一个包含两个数据源的演示。批处理元数据将存储在 H2 DB 中,作业数据源是 Azure SQL。

    这是项目结构:

    1. 我们需要定义一个DataSourceConfig 类并为DataSource bean 使用@Primary 注解:
    @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. 在ItemReaderDbDemo类中,我们使用@Autowired @Qualifier("mssqlDataSource")来指定Spring Batch任务中的dataSource:
    @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. 这是我的 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. 它从我的 Azure SQL 返回预期结果。顺便说一句,我的 Azure sql 用户名没有创建数据库的权限。
      结果显示:

    【讨论】:

    • 这是我的code
    • 谢谢。看起来不错。我自己还没有尝试实施。这几天没时间。我会尽快通知你。
    • 嗨@Abhinandan Madaan,如果我的回答对您有帮助,请接受(标记)它作为答案。这对其他社区成员可能是有益的。非常感谢。
    【解决方案2】:

    如何在本地数据库或内存数据库(如 h2db)中创建元数据表。

    您可以为此使用spring.batch.initialize-schema=embedded

    或者,如果我已经在主数据库中创建了元数据表,则使用与我从中获取的主表不同的架构。如何将我的工作指向另一个架构中的那些元数据表,以在其中存储工作和步骤详细信息数据。

    spring batch 作用于数据源,而不是特定的模式。如果元数据表位于不同的架构中,那么您需要创建第二个指向该架构的数据源并将其设置在作业存储库中。

    【讨论】:

    • 我找不到任何相关示例或相关文档。你能指点我一些吗,这对给我一些指导很有帮助。
    • 您可以在创建元数据表的数据源的spring.datasource.url 属性中指定架构,请参阅stackoverflow.com/questions/39430422/…。如果有帮助,请接受此答案。
    • 对不起,我还没有机会根据您的建议实施解决方案,被占用了。会的。
    猜你喜欢
    • 2020-08-09
    • 2021-08-12
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    相关资源
    最近更新 更多