是否有多个JdbcTemplate实例?

时间:2012-02-27 05:38:41

标签: java spring jdbctemplate

根据我的理解,DataSourceJdbcTemplates都是threadsafe,因此您可以配置JdbcTemplate的单个实例,然后安全地注入此共享引用到多个DAO(或存储库)。另外DataSource应该是Spring单例,因为它管理连接池。

官方Spring Documentation JdbcTemplate best practices解释了替代方案(手册的摘录用斜体字表示,方括号内的说明:

  • 在Spring配置文件中配置一个DataSource,然后依赖注入该共享DataSource bean到您的DAO类中; JdbcTemplate是在DataSource的setter中创建的。 [使用XML配置,这会导致多个JdbcTemplate实例,因为在数据源设置器中有new JdbcTemplate(dataSource)]
  • 使用组件扫描和注释支持依赖注入。在这种情况下,您使用@Repository注释该类(这使其成为组件扫描的候选者)并使用@Autowired注释DataSource setter方法。 [此情况也会导致多个JdbcTemplate实例]
  • 如果您正在使用Spring的JdbcDaoSupport类,并且您的各种JDBC支持的DAO类从它扩展,那么您的子类将从JdbcDaoSupport类继承setDataSource(..)方法。您可以选择是否继承此类。 JdbcDaoSupport类仅作为方便提供。 [因为你为扩展它的每个类都有一个JdbcDaoSupport实例,所以对于派生类的每个实例也有一个JdbcTemplate实例(参见source code for JdbcDaoSupport )]

但是,稍后的说明会阻止刚刚提出的所有选项:

  

配置完成后,JdbcTemplate实例就是线程安全的。如果您的应用程序访问多个数据库(可能需要多个DataSource,以及随后多个不同配置的JdbcTemplates),您可能需要多个JdbcTemplate实例。

换句话说,刚才提出的所有选项都会导致有多个JdbcTemplate实例(每个DAO一个),并且在文档说明使用单个数据库时不需要这样做。

我要做的是直接将JdbcTemplate注入需要它的各种DAO,所以我的问题是,这样做是否可以?而且,您是否也认为Spring参考文档是自相矛盾的?或者是我的误会?

4 个答案:

答案 0 :(得分:4)

IMO,将JdbcTemplate注入您的(多个)DAO是没有问题的。当您需要运行数据库查询时,该模板用于将DAO“连接”到物理资源(数据库连接)。因此,如果SessionFactory和TransactionManager已正确配置,您将不会遇到并发问题 - Spring管理您使用持久层所需的bean的生命周期。使用模板的好处是:

  1. JDBC模板管理自动与DB交互所需的物理资源,例如:创建并释放数据库连接。
  2. Spring JDBC模板将标准JDBC SQLExceptions转换为RuntimeExceptions。这使您可以更灵活地对错误做出反应。 Spring JDBC模板还将特定于供应商的错误消息转换为更易理解的错误消息

答案 1 :(得分:0)

所以它应该溢出两种情况:

我们不会在DAO中更改JdbcTemplate属性,我们可以定义如下:

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

注意:大多数时候我们不会更改JdbcTemplate属性,因为没有必要。

我们在DAO中更改JdbcTemplate属性,我们应该扩展JdbcDaoSupport。

State:
•   fetchSize: If this variable is set to a non-zero value, it will be used for setting the fetchSize property on statements used for query processing(JDBC Driver default)
•   maxRows: If this variable is set to a non-zero value, it will be used for setting the maxRows property on statements used for query processing(JDBC Driver default)
•   queryTimeout: If this variable is set to a non-zero value, it will be used for setting the queryTimeout property on statements used for query processing.(JDBC Driver default)
•   skipResultsProcessing: If this variable is set to true then all results checking will be bypassed for any callable statement processing.  This can be used to avoid a bug in some older Oracle JDBC drivers like 10.1.0.2.(false)
•   skipUndeclaredResults: If this variable is set to true then all results from a stored procedure call that don't have a corresponding SqlOutParameter declaration will be bypassed. All other results processing will be take place unless the variable {@code skipResultsProcessing} is set to {@code true}(false)
•   resultsMapCaseInsensitive: If this variable is set to true then execution of a CallableStatement will return the results in a Map that uses case insensitive names for the parameters if Commons Collections is available on the classpath.(false)
  1. JdbcDaoSupport

    公共抽象类JdbcDaoSupport扩展了DaoSupport {

    private JdbcTemplate jdbcTemplate;
    
    
    /**
     * Set the JDBC DataSource to be used by this DAO.
     */
    public final void setDataSource(DataSource dataSource) {
        if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
            this.jdbcTemplate = createJdbcTemplate(dataSource);
            initTemplateConfig();
        }
    }
    
  2. 总结:我不认为春天给予指导的做法是最好的。

答案 2 :(得分:0)

天生弹簧对最佳实践非常微妙。

JdbcTemplate是线程安全的,特别是无锁(v4.2.4)。 这意味着它不应该在并发线程*之间共享时导致性能下降。 因此,没有令人信服的理由为每个数据源提供多个实例。

投机性说明:此部分确实令人困惑。 可能是由于历史(进化)原因。 也许Spring过去因为非线程安全或一次域名不当而导致每个dao政策。 类似于基于xml的配置“灾难”。 如今春天放弃了自以为是的观点,并努力变得灵活。 不幸的是,这导致了糟糕的设计选择,只是隐蔽地承认。

* measure不要猜测

答案 3 :(得分:0)

这么多年后,再次看到这个问题,我认为我们可以先用单例创建“ Jdbc模板”,然后注入DAO,所以它只是该模板的一个实例。

DbContext

然后您可以将模板注入DAO或DAO扩展JdbcDaoSupport。

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