根据我的理解,DataSource
和JdbcTemplates
都是threadsafe
,因此您可以配置JdbcTemplate
的单个实例,然后安全地注入此共享引用到多个DAO(或存储库)。另外DataSource
应该是Spring单例,因为它管理连接池。
官方Spring Documentation JdbcTemplate best practices解释了替代方案(手册的摘录用斜体字表示,方括号内的说明:
new JdbcTemplate(dataSource)
] 但是,稍后的说明会阻止刚刚提出的所有选项:
配置完成后,JdbcTemplate实例就是线程安全的。如果您的应用程序访问多个数据库(可能需要多个DataSource,以及随后多个不同配置的JdbcTemplates),您可能需要多个JdbcTemplate实例。
换句话说,刚才提出的所有选项都会导致有多个JdbcTemplate实例(每个DAO一个),并且在文档说明使用单个数据库时不需要这样做。
我要做的是直接将JdbcTemplate
注入需要它的各种DAO,所以我的问题是,这样做是否可以?而且,您是否也认为Spring参考文档是自相矛盾的?或者是我的误会?
答案 0 :(得分:4)
IMO,将JdbcTemplate注入您的(多个)DAO是没有问题的。当您需要运行数据库查询时,该模板用于将DAO“连接”到物理资源(数据库连接)。因此,如果SessionFactory和TransactionManager已正确配置,您将不会遇到并发问题 - Spring管理您使用持久层所需的bean的生命周期。使用模板的好处是:
答案 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)
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 :(得分: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>