是否有多个JdbcTemplate实例?

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

官方Spring文档JdbcTemplate最佳实践解释了替代方案(手册摘录用斜体,方括号之间的注释:

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

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

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

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

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

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

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

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

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

   

注意:大多数时候我们不更改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(); } } 

总结:我不认为spring给予指导的做法是最好的。

弹簧本身对最佳实践非常微妙。

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

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

*措施不要猜