【问题标题】:how to use JdbcTemplate in a multithreaded environment?如何在多线程环境中使用 JdbcTemplate?
【发布时间】:2011-03-07 14:52:00
【问题描述】:

我正在尝试将 Spring JdbcTemplate 与 Spring 的 SimpleAsyncTaskExecutor 一起使用,以便与数据库的并发连接 与单线程环境相比,可以在更短的时间内将整个数据插入到相关表中。

我正在使用以下代码,但它不会加快我的应用程序。

我能找到的唯一线索是 bean “campaignProductDBWriter” 只构建一次,而我预计会创建 10 个单独的实例 因为我在 tasklet 中将“throttle-limit”设置为 10。

我做错了什么?任何帮助或建议将不胜感激。

问候,

<bean id="dataSourceProduct"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource"
  p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url.product}"
  p:username="${jdbc.username.product}" p:password="${jdbc.password.product}" 
/>

<bean id="jdbcTemplateProduct" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="dataSourceProduct" />
</bean>

<bean id="simpleTaskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" >
  <property name="concurrencyLimit" value="-1" />
</bean>

<batch:job id="sampleJob" restartable="true"  incrementer="dynamicJobParameters">             
  <batch:step id="mapMZList">
    <batch:tasklet allow-start-if-complete="true" task-executor="simpleTaskExecutor" throttle-limit="10">                     
      <batch:chunk reader="campaignProductItemReader" processor="campaignProductProcessor" writer="campaignProductDBWriter" commit-interval="5000"/>        
    </batch:tasklet>
  </batch:step>                 
</batch:job>

<bean id="campaignProductDBWriter" class="com.falcon.cc.job.step.CampaignProductWriter">
  <property name="jdbcTemplate" ref="jdbcTemplateProduct" />
</bean>


<bean id="campaignProductItemReader" class="com.falcon.cc.job.step.FlatFileSynchronizedItemReader" scope="step">    
  <property name="resource" value="file:#{jobParameters['input.TEST_FILE.path']}"/>

  <property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">        
      <property name="lineTokenizer">       
        <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
          <property name="delimiter" value=";"/>            
          <property name="names" value="approvalStatus,validFrom,validTo"/>
        </bean>
      </property>
      <property name="fieldSetMapper">
        <bean class="com.falcon.cc.mapper.CampaignProductFieldSetMapper" />
      </property>
    </bean>
  </property>
</bean>

【问题讨论】:

  • 只是一般观察,许多 JDBC 驱动程序不是线程安全的,因此要安全运行 10 个线程,您需要 10 个连接。您是否尝试过使用 BatchUpdate?虽然我也听说过那里有困难。
  • @skaffman "没有变化" 这不是真的,即使在规范中,从规范 "例如,同一连接上的两个语句可以同时执行并且它们的结果集可以被处理并发(从开发人员的角度来看)。一些驱动程序将提供这种完全并发。其他人可能会执行一个语句并等到它完成后再发送下一个。我知道线程安全是 Oracle OCI for 9i 中的一个新特性。所以我猜你是对的,它们应该是线程安全的......但并非所有这些都保证同时有用。

标签: java multithreading jdbc jdbctemplate spring-batch


【解决方案1】:

这不是您的 Spring 配置的问题,也不是您使用 jdbcTemplate 的问题,它只是 JDBC API 的一个薄的、无状态的包装器。

最明显的可能性是您的瓶颈是您的数据库,而不是您的代码。完全有可能对数据库运行多个并发操作并不比一次执行一个快。

这可能有多种原因,例如数据库锁定,或者只是缺乏原始 I/O 性能。

在考虑使用多线程来提高性能时,您必须确定瓶颈在哪里。如果您的代码不是瓶颈,那么将其设为多线程不会让事情变得更快。

【讨论】:

  • 感谢您的回答,但我仍然很好奇为什么 beancampaignProductDBWriter 只构造一次,而我期望构造 10 个不同的实例。我想我错过了什么。
【解决方案2】:

当spring的上下文被初始化时,它会创建所有在上下文中声明的实例。 <bean id="campaignProductDBWriter" class="com.falcon.cc.job.step.CampaignProductWriter"> <property name="jdbcTemplate" ref="jdbcTemplateProduct" /> </bean> 此代码将导致 spring 创建一个 CampaignProductWriter 的实例,这将是一个单例(默认情况下,范围是单例)。 为了有一个新的 bean 实例,它的作用域必须是原型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多