问题的分析
我首先想到在spring但是,我很快发现一个问题:当多用户同时并发访问数据库的时候会出现资源争用的问题。这都是“单例模式”惹的祸。众所周知,我们在使用spring通过以上的分析,解决多数据源访问问题的关键,就集中在sessionFactory(一) 采用Decorator设计模式
要解决这个问题,我的思路锁定在了这个dataSource什么是“
(二) 设计MultiDataSource类
现在回到我们的问题,我们需要对dataSource
对比原Decorator
private DataSource dataSource = null;
public MultiDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
/* (non-Javadoc)
* @see javax.sql.DataSource#getConnection()
*/
public Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
//其它DataSource接口应当实现的方法
public DataSource getDataSource(){
return this.dataSource;
}
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
客户在发出请求的时候,将dataSourceName放到request中,然后把request中的数据源名通过调用new MultiDataSource(dataSource)时可以告诉客户需要的数据源,就可以实现动态切换数据源了。但细心的朋友会发现这在单例的情况下就是问题的,因为在系统中只有一个对象,它的实例变量也只有一个,就如同一个静态变量一般。正因为如此,(三) 单例模式下的MultiDataSource
在单例模式下,由于我们在每次调用MultiDataSource
log.debug("dataSourceName:"+dataSourceName);
try{
if(dataSourceName==null||dataSourceName.equals("")){
return this.dataSource;
}
return (DataSource)this.applicationContext.getBean(dataSourceName);
}catch(NoSuchBeanDefinitionException ex){
throw new DaoException("There is not the dataSource
}
}
值得一提的是,我需要的数据源已经都在spring就是其对应的bean id="dataSource1"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDrivervalue>
property>
......
bean>
<bean id="dataSource2"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDrivervalue>
property>
......
bean>
为了得到spring,并且实现方法:
java 代码
- private ApplicationContext applicationContext = null;
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
如此这样,我就可以通过得到了。
(四) 通过线程传递dataSourceName
查看以上设计,MultiDataSource
class SpObserver {
private static ThreadLocal local = new ThreadLocal();
public static void putSp(String sp) {
local.set(sp);
}
public static String getSp() {
return (String)local.get();
}
}
做一个filter,将request中的dataSourceName对象。
String sp = SpObserver.getSp();
return getDataSource(sp);
}
完整的MultiDataSource(五) 动态添加数据源
通过以上方案,我们解决了动态分配数据源的问题,但你可能提出疑问:方案中的数据源都是配置在spring中(见附件)。不通过配置文件直接加载对象,在的源码中也有,感兴趣的朋友可以自己研究。
(六) 在spring中配置
在完成了所有这些设计以后,我最后再唠叨一句。我们应当在springbean id="dynamicLoadBean" class="com.htxx.service.dao.DynamicLoadBean">bean>
<bean id="dataSource" class="com.htxx.service.dao.MultiDataSource">
<property name="dataSource">
<ref bean="dataSource1" />
property>
bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
property>
......
bean>
其中dataSource以上方案与其它方案相比,它有哪些优势呢?
首先,这个方案完全是在spring其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有MultiDataSource最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响BUS相关博客:再析在spring框架中解决多数据源的问题
|
example.rar |
描述: |
源码及示例 |
下载 |
文件名: |
example.rar |
文件大小: |
32 KB |
下载过的: |
文件被下载或查看 521 次 |
关键字: Spring Hibernate Decorator 设计模式
如何在spring总结多数据源的问题,其实它需要分为以下三种情况:各个数据源的数据结构不同、各个数据源的数据结构相同、各个数据源的数据结构部分相同又有部分不同。对于第二种情况,各个数据源的数据结构相同,我们使用一个sessionFactory对于各个数据源的数据结构不同的情况,使用一个sessionFactory与MultiDataSource
在该方案中,SessionFactory接口,Decorator就是MultiSessionFactory,SessionFactory1和SessionFactory2往往是spring的。细心的朋友可能会注意,实际上并不是SessionFactory的时候其实并不是真正地得到了它,而是得到了一个SessionFactory重写了getObject()。在整个这个方案中,我们需要实现的只有MultiSessionFactory。MultiSessionFactoryclass MultiSessionFactory implements SessionFactory, ApplicationContextAware {
private static final long serialVersionUID = 2064557324203496378L;
private static final Log log = LogFactory.getLog(MultiSessionFactory.class);
private ApplicationContext applicationContext = null;
private SessionFactory sessionFactory = null;
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public SessionFactory getSessionFactory(String sessionFactoryName) {
log.debug("sessionFactoryName:"+sessionFactoryName);
try{
if(sessionFactoryName==null||sessionFactoryName.equals("")){
return sessionFactory;
}
return (SessionFactory)this.getApplicationContext().getBean(sessionFactoryName);
}catch(NoSuchBeanDefinitionException ex){
throw new DaoException("There is not the sessionFactory
}
}
public SessionFactory getSessionFactory() {
String sessionFactoryName = SpObserver.getSp();
return getSessionFactory(sessionFactoryName);
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// SessionFactory接口需要实现的方法
......
}
MultiSessionFactory的完整代码见我提供的附件。bean id="sessionFactory" class="com.htxx.service.dao.MultiSessionFactory">
<property name="sessionFactory"><ref bean="hostSessionFactory"/>property>
>
SpServer的写法与《如何在另外,在spring也许有些朋友对以上方案还不满意,因为在执行数据访问前毕竟还要多做一步指定sessionFactory另外,在这个方案中的核心是运用Decorator前面我已经给出了第一种和第二种情况的解决方案:各个数据源的数据结构不同的情况用MultiSessionFactory
example.rar |
描述: |
示例文件 |
下载 |
文件名: |
example.rar |
文件大小: |
16 KB |
下载过的: |
文件被下载或查看 180 次 |
|
建议到原作者博客查看原文,那里有很好的回复讨论~http://fangang.javaeye.com/blog/72486