zoukankan      html  css  js  c++  java
  • Spring多数据源的配置与使用

    从单数据源转变到多数据源的环境,应用程序面临的其中一个问题是,不同的模块对应不同的数据源,如何透明地使用不同的数据源,达到程序的最小改动。

    Spring框架提供了自定义数据源路由功能,可以根据规则获取不同的数据源。

    实现思路:参考Oliver Gierke在stackoverflow上的回复

     剽窃一张图片说明一下(原文链接),图片中的DynamicDataSource对应下面配置中的dataSource

    主要配置:

    <!-- 配置两个数据源 -->
        <bean id="dsa" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
            <property name="driver">
                <bean class="com.mysql.jdbc.Driver"></bean>
            </property>
            <property name="url" value="jdbc:mysql://localhost:3306/da" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </bean>
        
        <bean id="dsb" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
            <property name="driver">
                <bean class="com.mysql.jdbc.Driver"></bean>
            </property>
            <property name="url" value="jdbc:mysql://localhost:3306/db" />
            <property name="username" value="root" />
            <property name="password" value="root" />
        </bean>
    <!-- 自定义数据源路由规则 -->
        <bean id="dataSource" class="jpa.data.ds.CustomerRoutingDataSource">
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <entry key="a" value-ref="dsa" />
                    <entry key="b" value-ref="dsb" />
                </map>
            </property>
            <property name="defaultTargetDataSource" ref="dsa" />
        </bean>

    这样所有需要数据源的地方统一跟dataSource对象打交道,由它根据规则返回对应的数据源。

    dataSource实现代码:

    public class CustomerRoutingDataSource extends AbstractRoutingDataSource {
    
        @Override
        protected Object determineCurrentLookupKey() {
            return CustomerContextHolder.getName();
        }
    
    }
    public class CustomerContextHolder {
    
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    
        public static void setName(String name) {
            contextHolder.set(name);
        }
    
        public static String getName() {
            return contextHolder.get();
        }
    
    }

    透明地使用多数据源:

    // 采用Spring+JPA方式实现
        public void find() {
            CustomerContextHolder.setName("a");    // 选择dsa数据源
            User user = userRepository.findOne(1L); // 获取的是dsa数据源
            assertNotNull(user);
            
            CustomerContextHolder.setName("b");    // 选择dsb数据源
            Photo photo = photoRepository.findOne(1L); // 获取的是dsb数据源
            assertNotNull(photo);
        }

     在代码中,每次使用不同的数据源都需要切换,想象一下,每个访问数据库的地方都要写这行切换代码,这很难让人接受。但仔细想想,这个需求跟日志、异常处理很类似,根据经验,我们可以把数据源切换的代码提取出来,用AOP的方式把它嵌入到所有需要访问数据库的地方,切换规则可以自定义。

    应用场景:

    不同的模块对应不同的数据源,可以根据包名对应模块名,然后按模块来切换数据源。

    读写分离的数据库集群,相应模块的更新操作对应一个数据源,所有的读操作对应另一个数据源。读写分离的优势还在于,可以针对读、写需求专门优化相应的数据库。

    参考:

    Dynamic DataSource Routing

    spring动态创建,加载,使用多数据源

  • 相关阅读:
    PHP探针
    服务器fsockopen函数和pfsockopen函数开启及作用
    WP SMTP插件为啥我一直设置的不对?
    用WP SMTP插件实现邮件发送功能
    openssl基本原理 + 生成证书 + 使用实例
    解决wordpress无法发送邮件的问题|配置好WP-Mail-SMTP的前提
    使用 openssl 生成证书
    如何使用OpenSSL工具生成根证书与应用证书
    OpenSSL 给自己颁发根证书,由根证书签发下级证书的步骤。
    ARMCC和GCC编译ARM代码的软浮点和硬浮点问题【转】
  • 原文地址:https://www.cnblogs.com/huangyp/p/3630273.html
Copyright © 2011-2022 走看看