当前位置: 首页 > 面试题库 >

如何为Spring Batch数据和业务数据Java配置单独的数据源?我应该做吗?

姬承教
2023-03-14
问题内容

我的主要工作是只读取操作,而另一项工作是写操作,但是MyISAM engine忽略了事务,因此我不需要事务支持。我Spring Batch该如何配置,使其拥有自己的数据源,而JobRepository不是保存业务数据的数据源?最初的一个数据源配置如下所示:

@Configuration
public class StandaloneInfrastructureConfiguration {

    @Autowired
    Environment env;

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(dataSource());
      em.setPackagesToScan(new String[] { "org.podcastpedia.batch.*" });

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      em.setJpaVendorAdapter(vendorAdapter);
      em.setJpaProperties(additionalJpaProperties());

      return em;
    }

    Properties additionalJpaProperties() {
          Properties properties = new Properties();
          properties.setProperty("hibernate.hbm2ddl.auto", "none");
          properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
          properties.setProperty("hibernate.show_sql", "true");

          return properties;
    }

    @Bean
    public DataSource dataSource(){

       return DataSourceBuilder.create()
                .url(env.getProperty("db.url"))
                .driverClassName(env.getProperty("db.driver"))
                .username(env.getProperty("db.username"))
                .password(env.getProperty("db.password"))
                .build();          
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(emf);

      return transactionManager;
    }
}

然后将其导入Job的配置类中,@EnableBatchProcessing注释将自动使用该配置类。我最初的想法是尝试设置扩展扩展的配置类DefaultBatchConfigurer,但是随后我得到了

BeanCurrentlyInCreationException(org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为jobBuilders的bean时出错:当前正在创建请求的bean:是否存在不可解析的循环引用?):

@Configuration
@EnableBatchProcessing
@Import({StandaloneInfrastructureConfiguration.class, NotifySubscribersServicesConfiguration.class})
public class NotifySubscribersJobConfiguration extends DefaultBatchConfigurer {

    @Autowired
    private JobBuilderFactory jobBuilders;

    @Autowired
    private StepBuilderFactory stepBuilders;

    @Autowired
    private DataSource dataSource;

    @Autowired
    Environment env;

    @Override
    @Autowired
    public void setDataSource(javax.sql.DataSource dataSource) {
        super.setDataSource(batchDataSource());
    }

    private DataSource batchDataSource(){          
       return DataSourceBuilder.create()
                .url(env.getProperty("batchdb.url"))
                .driverClassName(env.getProperty("batchdb.driver"))
                .username(env.getProperty("batchdb.username"))
                .password(env.getProperty("batchdb.password"))
                .build();          
    } 

    @Bean
    public ItemReader<User> notifySubscribersReader(){

        JdbcCursorItemReader<User> reader = new JdbcCursorItemReader<User>();
        String sql = "select * from users where is_email_subscriber is not null";

        reader.setSql(sql);
        reader.setDataSource(dataSource);
        reader.setRowMapper(rowMapper());       

        return reader;
    }
........
}  

问题答案:

好的,这很奇怪,但是可以。将数据源移动到它自己的配置类中可以很好地工作,并且能够自动装配。

该示例是Spring Batch Service Example的多数据源版本:

DataSourceConfiguration:

public class DataSourceConfiguration {

    @Value("classpath:schema-mysql.sql")
    private Resource schemaScript;

    @Bean
    @Primary
    public DataSource hsqldbDataSource() throws SQLException {
        final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriver(new org.hsqldb.jdbcDriver());
        dataSource.setUrl("jdbc:hsqldb:mem:mydb");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public DataSource mysqlDataSource() throws SQLException {
        final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriver(new com.mysql.jdbc.Driver());
        dataSource.setUrl("jdbc:mysql://localhost/spring_batch_example");
        dataSource.setUsername("test");
        dataSource.setPassword("test");
        DatabasePopulatorUtils.execute(databasePopulator(), dataSource);
        return dataSource;
    }

    @Bean
    public JdbcTemplate mysqlJdbcTemplate(@Qualifier("mysqlDataSource") final DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    private DatabasePopulator databasePopulator() {
        final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScript(schemaScript);
        return populator;
    }
}

BatchConfiguration:

@Configuration
@EnableBatchProcessing
@Import({ DataSourceConfiguration.class, MBeanExporterConfig.class })
public class BatchConfiguration {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public ItemReader<Person> reader() {
        final FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
        reader.setResource(new ClassPathResource("sample-data.csv"));
        reader.setLineMapper(new DefaultLineMapper<Person>() {
            {
                setLineTokenizer(new DelimitedLineTokenizer() {
                    {
                        setNames(new String[] { "firstName", "lastName" });
                    }
                });
                setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {
                    {
                        setTargetType(Person.class);
                    }
                });
            }
        });
        return reader;
    }

    @Bean
    public ItemProcessor<Person, Person> processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public ItemWriter<Person> writer(@Qualifier("mysqlDataSource") final DataSource dataSource) {
        final JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
        writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
        writer.setDataSource(dataSource);
        return writer;
    }

    @Bean
    public Job importUserJob(final Step s1) {
        return jobs.get("importUserJob").incrementer(new RunIdIncrementer()).flow(s1).end().build();
    }

    @Bean
    public Step step1(final ItemReader<Person> reader,
            final ItemWriter<Person> writer, final ItemProcessor<Person, Person> processor) {
        return steps.get("step1")
                .<Person, Person> chunk(1)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .build();
    }
}


 类似资料:
  • 我的主要工作只做读操作,另一个工作做一些写操作,但在上,它忽略了事务,所以我不需要事务支持。如何配置使拥有自己的数据源,而不是保存业务数据的数据源?初始的一个数据源配置如下所示: 然后在的配置类中导入它,注释自动使用它。我最初的想法是尝试设置配置类扩展,但后来我得到了一个 BeanCurrentlyInCreationException(org.SpringFramework.Beans.Fact

  • springboot项目,想要对某个指定的业务逻辑,比如客户订单的修改做日志,我的想法是每次客户订单不管修改了什么要素都将修改前的数据保存到另外一个结构完全相同的表中。比如订单表示 order,那么我就创建一个结构完全相同的表 order_log 用来保存订单每次修改前的数据,最终可以看到一个流水数据,就是某个订单在什么时间都被什么账号修改过哪个要素。这个做法是否太笨重?有没有其他更好的实现方法?

  • 在建造中。我有:

  • 配置项说明 schemaName: # 逻辑数据源名称 dataSources: # 数据源配置,可配置多个 <data-source-name> <data-source-name>: # 与 ShardingSphere-JDBC 配置不同,无需配置数据库连接池 url: #数据库 URL 连接 username: # 数据库用户名 password: # 数据库

  • 问题内容: 目前,我正在使用带有@Transactional批注的DriverManagerDataSource来管理事务。但是所有事务都非常非常慢,这可能是因为数据源每次都打开和关闭与db的连接。 我应该使用什么数据源来加快交易速度? 问题答案: 实际上不是连接池,只能用于测试。您应该尝试使用Apache Commons DBCP 。就像是:

  • 我在我的application.properties文件中定义了一个数据源: 但是,当我尝试运行我的camelway时,我得到了这个错误:"在注册表中找不到bean:类型为:javax.sql.数据源的数据源"。我总是在Spring配置我的数据源,使用application.properties文件没有问题。 完整的错误日志: 我的骆驼路线: 编辑:我以编程方式添加了数据源,如下所示: 但是,现在