技术库 > Java

spring中配置多数据库读取

技术库:tec.5lulu.com

from:tec.5lulu.com

在应对大量用户读取的系统中,对数据库的操作通常采用读写分离方式,往一个数据库写入,然后通过复制将数据同步到另外的多个数据库中,读操作都从这些数据库中操作,在采用spring来配置多数据库时,并不能直接支持从多个DataSource中获得数据库连接,为此需要开发一个DataSource的代理,代理实现javax.sql.DataSource接口。该代理根据一定的策略从已有的多个DataSource中选择一个,提供给SessionFactory,供数据访问层使用。原理如下图所示:

spring中配置多数据库读取,by 5lulu.com


DataSource Proxy选择DataSource的方式可以根据实际进行设计,这里为简单,就采用随机方式选择一个。源代码如下:

package code;  
  
import java.io.PrintWriter;  
import java.sql.Connection;  
import java.sql.SQLException;  
  
import java.util.List;  
import java.util.Random;  
  
import javax.sql.DataSource;  
  
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
  
public class RandomDataSource  implements DataSource {  
  
    private List<DataSource> dataSourcePool ;  
    protected Log log =  LogFactory.getLog(getClass());  
      
    private  static ThreadLocal<DataSource> dsHolder = new ThreadLocal<DataSource>();  
      
      
    /** 
     * 从已有DataSource中随机选择一个 
     * 
     * 
     */  
    private DataSource randomDs(){  
          
        int size = dataSourcePool.size();  
          
        Random r= new Random();  
          
        int t = r.nextInt(size);  
          
        dsHolder.set(dataSourcePool.get(t));  
        return dsHolder.get();  
          
          
    }  
      
      
    @Override  
    public Connection getConnection() throws SQLException {  
          
        Connection conn = randomDs().getConnection();  
        log.info("conn URL---->"+conn.getMetaData().getURL());  
        return conn;  
    }  
  
    @Override  
    public Connection getConnection(String username, String password)  
            throws SQLException {  
        // TODO Auto-generated method stub  
          
        Connection conn = randomDs().getConnection(username, password);  
          
          
        return conn;  
    }  
  
    @Override  
    public PrintWriter getLogWriter() throws SQLException {  
          
        return dsHolder.get().getLogWriter();  
    }  
  
    @Override  
    public int getLoginTimeout() throws SQLException {  
        // TODO Auto-generated method stub  
        return dsHolder.get().getLoginTimeout();  
    }  
  
    @Override  
    public void setLogWriter(PrintWriter out) throws SQLException {  
        // TODO Auto-generated method stub  
        dsHolder.get().setLogWriter(out);  
    }  
  
    @Override  
    public void setLoginTimeout(int seconds) throws SQLException {  
        // TODO Auto-generated method stub  
        dsHolder.get().setLoginTimeout(seconds);  
    }  
  
    @Override  
    public boolean isWrapperFor(Class<?> iface) throws SQLException {  
        // TODO Auto-generated method stub  
        return dsHolder.get().isWrapperFor(iface);  
    }  
  
    @Override  
    public <T> T unwrap(Class<T> iface) throws SQLException {  
        // TODO Auto-generated method stub  
        return dsHolder.get().unwrap(iface);  
    }  
  
    public List<DataSource> getDataSourcePool() {  
        return dataSourcePool;  
    }  
  
    public void setDataSourcePool(List<DataSource> dataSourcePool) {  
          
        this.dataSourcePool = dataSourcePool;  
    }  
  
}  

为了可用性,实际生产环境中需要判断取到的DataSource对应的数据库是否可访问,若不能访问,则要取其他可用的DataSource。

在springframework中的配置如下:

<bean id="dataSource" class="code.RandomDataSource">  
        <property name="dataSourcePool">  
            <list>  
                <ref bean="dataSource1" />  
                <ref bean="dataSource2" />  
            </list>  
        </property>  
    </bean>  
      
      
    <bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
        <property name="jdbcUrl" value="jdbc:mysql://192.168.2.192/ebook"/>  
        <property name="user" value="test"/>  
        <property name="password" value="test"/>  
    </bean>  
      
     <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>  
        <property name="jdbcUrl" value="jdbc:mysql://192.168.2.105/ebook"/>  
        <property name="user" value="test"/>  
        <property name="password" value="test"/>  
    </bean>  
      
      
    <!-- Hibernate SessionFactory -->  
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
                <prop key="hibernate.show_sql">true</prop>  
                <prop key="hibernate.format_sql">true</prop>  
                  
            </props>  
        </property>  
        <property name="dataSource" ref="dataSource"/>            
          
    </bean>  

这里连接的是MySQL数据库,如果是其他数据库,需要将DataSource1和DataSource2中的参数以及hibernate.dialect做相应修改。

spring中配置多数据库读取


本文链接 http://tec.5lulu.com/detail/110dan2ehtgra85be.html

我来评分 :6.1
0

转载注明:转自5lulu技术库

本站遵循:署名-非商业性使用-禁止演绎 3.0 共享协议

www.5lulu.com