【问题标题】:Spring batch with google spanner with no in memory database带有谷歌扳手的春季批处理,没有内存数据库
【发布时间】:2019-12-09 16:25:00
【问题描述】:

我正在考虑使用 Google Spanner 作为数据库来实现 Spring Batch 作业,但 Spring Batch 只需要标准数据库,我不想使用内存数据库/外部数据库来执行此操作,我想存储所有Google Spanner 中的作业元数据,我该如何实现呢?使用 GCP spanner 实施的专家有什么意见吗?

我提到了这个答案Data Source for GCP Spanner 得到以下错误

Caused by: java.lang.IllegalArgumentException: DatabaseType not found for product name: [Google Cloud Spanner]
at org.springframework.batch.support.DatabaseType.fromProductName(DatabaseType.java:84) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.support.DatabaseType.fromMetaData(DatabaseType.java:123) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.repository.support.JobRepositoryFactoryBean.afterPropertiesSet(JobRepositoryFactoryBean.java:183) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer.createJobRepository(BasicBatchConfigurer.java:129) ~[spring-boot-autoconfigure-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer.initialize(BasicBatchConfigurer.java:97) ~[spring-boot-autoconfigure-2.2.2.RELEASE.jar:2.2.2.RELEASE]
... 26 common frames omitted

配置代码如下,

package io.spring.batchdemo.config;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer;
import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class BatchConfig2 implements BatchConfigurer {
    private final BatchProperties properties;

    private PlatformTransactionManager transactionManager;

    private final TransactionManagerCustomizers transactionManagerCustomizers;

    private JobRepository jobRepository;

    private JobLauncher jobLauncher;

    private JobExplorer jobExplorer;

    /**
     * Create a new {@link BasicBatchConfigurer} instance.
     * @param properties the batch properties
     * @param dataSource the underlying data source
     * @param transactionManagerCustomizers transaction manager customizers (or
     * {@code null})
     */
    protected BatchConfig2(BatchProperties properties,
            TransactionManagerCustomizers transactionManagerCustomizers) {
        this.properties = properties;
        this.transactionManagerCustomizers = transactionManagerCustomizers;
    }

    @Override
    public JobRepository getJobRepository() {
        return this.jobRepository;
    }

    @Override
    public PlatformTransactionManager getTransactionManager() {
        return this.transactionManager;
    }

    @Override
    public JobLauncher getJobLauncher() {
        return this.jobLauncher;
    }

    @Override
    public JobExplorer getJobExplorer() throws Exception {
        return this.jobExplorer;
    }

    @PostConstruct
    public void initialize() {
        try {
            this.transactionManager = buildTransactionManager();
            this.jobRepository = createJobRepository();
            this.jobLauncher = createJobLauncher();
            this.jobExplorer = createJobExplorer();
        }
        catch (Exception ex) {
            throw new IllegalStateException("Unable to initialize Spring Batch", ex);
        }
    }

    protected JobExplorer createJobExplorer() throws Exception {
        PropertyMapper map = PropertyMapper.get();
        JobExplorerFactoryBean factory = new JobExplorerFactoryBean();
        factory.setDataSource(spannerDataSource());
        map.from(this.properties::getTablePrefix).whenHasText().to(factory::setTablePrefix);
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    protected JobLauncher createJobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(getJobRepository());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        PropertyMapper map = PropertyMapper.get();
        map.from(spannerDataSource()).to(factory::setDataSource);
        map.from(this::determineIsolationLevel).whenNonNull().to(factory::setIsolationLevelForCreate);
        map.from(this.properties::getTablePrefix).whenHasText().to(factory::setTablePrefix);
        map.from(this::getTransactionManager).to(factory::setTransactionManager);
        factory.afterPropertiesSet();
        factory.setDatabaseType("spanner");//which datatype to set?, here is the error,Caused by: java.lang.IllegalArgumentException: DatabaseType not found for product name: [Google Cloud Spanner]
        return factory.getObject();
    }

    /**
     * Determine the isolation level for create* operation of the {@link JobRepository}.
     * @return the isolation level or {@code null} to use the default
     */
    protected String determineIsolationLevel() {
        return null;
    }

    protected PlatformTransactionManager createTransactionManager() {
        return new DataSourceTransactionManager(spannerDataSource());
    }

    private PlatformTransactionManager buildTransactionManager() {
        PlatformTransactionManager transactionManager = createTransactionManager();
        if (this.transactionManagerCustomizers != null) {
            this.transactionManagerCustomizers.customize(transactionManager);
        }
        return transactionManager;
    }


    @Bean
    public DataSource spannerDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.google.cloud.spanner.jdbc.JdbcDriver");
        dataSource.setUrl("jdbc:cloudspanner:/projects/suresh-project-261506/instances/suresh-spanner/databases/spanner?credentials=C:\\Users\\skengab\\AppData\\Roaming\\gcloud\\application_default_credentials.json");
        return dataSource;
    }

}

pom.xml 在这里

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.spring</groupId>
    <artifactId>batch-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>batch-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-storage</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-spanner-jdbc</artifactId>
            <version>1.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

【问题讨论】:

标签: spring spring-boot spring-batch google-cloud-spanner


【解决方案1】:

Spring Batch 仅对一组固定的数据库提供官方支持。 Google Cloud Spanner 不是其中之一。如果要将 Spring Batch 与 Spanner 一起使用,则需要手动将数据库类型设置为受支持的数据库之一。然后 Spring Batch 将根据该设置生成查询和其他命令,这意味着您可能会收到与 Spanner 不兼容的查询有关的错误。

如果您可以忍受上述限制,我建议您尝试将数据库类型设置为 POSTGRES,即将以下行从

factory.setDatabaseType("spanner");//which datatype to set?, here is the error,Caused by: java.lang.IllegalArgumentException: DatabaseType not found for product name: [Google Cloud Spanner]

进入:

factory.setDatabaseType("POSTGRES");

【讨论】:

  • 奥拉夫,这不起作用,即使我尝试设置相同。
  • @SureshKb 设置此选项时收到什么错误消息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2020-07-22
  • 2022-08-02
  • 2014-12-15
  • 2018-05-27
  • 2015-05-13
  • 2017-06-25
相关资源
最近更新 更多