`
干宝周
  • 浏览: 14288 次
社区版块
存档分类
最新评论

spring多数据源

阅读更多

一。目的

在组内方便的切换主库和从库

 

二。具体做法

代码部分改动

1. 增加了一个注解DataSourceChange

 

public @interface DataSourceChange {

    boolean fromSlave() default false;

}

 

2. 增加了MultipleDataSourceInterceptor

在这个函数里,利用AOP,将当前的DataSourceNameContextHolder 切换到从库上

主要需要关注的代码是

 

   //为了减少影响面,目前只对×Service类里拥有DataSourceChange注解方法 进行AOP

    private final static String EDP = "execution(@com.DataSourceChange * com" +

            "..*Service.*(..))";

 

  

   // 这是切换DataSourceNameContextHolder的部分代码

     try {

            if (fromSlave) {

                DataSourceNameContextHolder.set(DataSourceNameConstant.SLAVE);

            }

            obj = joinPoint.proceed(args);

        } catch (Throwable e) {

            e.printStackTrace();

        } finally {

            if (fromSlave) {

                DataSourceNameContextHolder.clear();

            }

        }

 

3.增加了一个Wrapper

将原来ProductDao的部分方法挪了出来,放在这里,使用方法

 

    @DataSourceChange(fromSlave = true)

    public List<String> getIncludeSupplierIds() {

        return xxDao.getIncludeSupplierIds();

    }

 

三。验证方法

打开spring连接transaction的日志,查看使用了哪个连接。

 

四。结论

 

1. 如何使用

如果想让某个由Spring管理的Service里的某个方法访问从库,只需要给Service加上注解 @DataSourceChange(fromSlave = true), 则这个Service里的方法会自动访问从库。(前提是,Service里的DAO是由spring+mybatis管理的).

譬如

 

    @DataSourceChange(fromSlave = true)

    public List<String> fooA() {

        return xxx.fooA();

    }

 

2. 不足

我尝试过,将这个注解加到DAO这一层,譬如

 

@Repository

public interface xxDao {

 

     @DataSourceChange(fromSlave = true)

    List<String> fooA();

}

启动时Spring会报错,提示 Could not generate CGLIB subclass of final class.

猜测原因可能是 mybatis 自动生成Mapper类时,使用了CGLIB。 但是在spring再对这个interface进行代理时,必须用JDK默认的proxy才行。。所以这里可能会有冲突。 

还希望有别的同学能来指导具体的原因

 

如果这个service有@Transaction注解时,也不能使用这种方法。。。 这好像是Spring的一个bug,使用Transaction时,只会使用默认的dataSource

(已经由组内其他同事解决了。)

0
0
分享到:
评论
8 楼 干宝周 2014-08-10  
7454103 写道


这个问题也可以解决!事务方法的 datasoruce也是可以指定的!
@DataSourceChange 加个属性即可
能说下你们的解决方案不!分享下哈!或者邮件 沟通  jspp@qq.com


我们后来的解决方法绕开了多数据源事务的问题。
如果您非要使用多数据源的事务,你可以google搜索一下吧,很多的~
7 楼 干宝周 2014-07-29  
liubey 写道
handong890 写道
liubey 写道
handong890 写道
你如果用spring
完全不需要这样做,你只需要实现spring提供一个抽象类AbstractRoutingDataSource 即可完成多数据配置,并且可以在代码逻辑中切换数据源


你说的是“在代码逻辑中切换数据源”显然没有这个注解的更简洁,LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来



你可以在代码中切换数据源
也可以配置AOP规则自动切换,也可以自己加注解实现功能
比如 读写分离我们的规则是  queryXXX方法到指定库 其它方法到什么库。我只是告诉你SPRING 本来就有RoutingDataSource,没必要重复制造轮子



LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来
看清再回复,谢谢,这不是bug,别那么急


@liubey 你懂我~
6 楼 liubey 2014-07-08  
handong890 写道
liubey 写道
handong890 写道
你如果用spring
完全不需要这样做,你只需要实现spring提供一个抽象类AbstractRoutingDataSource 即可完成多数据配置,并且可以在代码逻辑中切换数据源


你说的是“在代码逻辑中切换数据源”显然没有这个注解的更简洁,LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来



你可以在代码中切换数据源
也可以配置AOP规则自动切换,也可以自己加注解实现功能
比如 读写分离我们的规则是  queryXXX方法到指定库 其它方法到什么库。我只是告诉你SPRING 本来就有RoutingDataSource,没必要重复制造轮子



LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来
看清再回复,谢谢,这不是bug,别那么急
5 楼 handong890 2014-07-08  
liubey 写道
handong890 写道
你如果用spring
完全不需要这样做,你只需要实现spring提供一个抽象类AbstractRoutingDataSource 即可完成多数据配置,并且可以在代码逻辑中切换数据源


你说的是“在代码逻辑中切换数据源”显然没有这个注解的更简洁,LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来



你可以在代码中切换数据源
也可以配置AOP规则自动切换,也可以自己加注解实现功能
比如 读写分离我们的规则是  queryXXX方法到指定库 其它方法到什么库。我只是告诉你SPRING 本来就有RoutingDataSource,没必要重复制造轮子
4 楼 liubey 2014-07-08  
7454103 写道
猜测原因可能是 mybatis 自动生成Mapper类时,使用了CGLIB。 但是在spring再对这个interface进行代理时,必须用JDK默认的proxy才行。。所以这里可能会有冲突
-------------- Spring使用哪个作为代理 在你的配置文件内可以指定的!
<aop:aspectj-autoproxy proxy-target-class="true"/>  试试这个配置


如果这个service有@Transaction注解时,也不能使用这种方法。。。 这好像是Spring的一个bug,使用Transaction时,只会使用默认的dataSource
(已经由组内其他同事解决了。)

这个问题也可以解决!事务方法的 datasoruce也是可以指定的!
@DataSourceChange 加个属性即可
能说下你们的解决方案不!分享下哈!或者邮件 沟通  jspp@qq.com



@Transactional可以指定具体事务transactionManager,不知道LZ是不是这么解决的
3 楼 liubey 2014-07-08  
handong890 写道
你如果用spring
完全不需要这样做,你只需要实现spring提供一个抽象类AbstractRoutingDataSource 即可完成多数据配置,并且可以在代码逻辑中切换数据源


你说的是“在代码逻辑中切换数据源”显然没有这个注解的更简洁,LZ也应该用AbstractRoutingDataSource了吧,只是没表示出来
2 楼 handong890 2014-07-06  
你如果用spring
完全不需要这样做,你只需要实现spring提供一个抽象类AbstractRoutingDataSource 即可完成多数据配置,并且可以在代码逻辑中切换数据源
1 楼 7454103 2014-07-06  
猜测原因可能是 mybatis 自动生成Mapper类时,使用了CGLIB。 但是在spring再对这个interface进行代理时,必须用JDK默认的proxy才行。。所以这里可能会有冲突
-------------- Spring使用哪个作为代理 在你的配置文件内可以指定的!
<aop:aspectj-autoproxy proxy-target-class="true"/>  试试这个配置


如果这个service有@Transaction注解时,也不能使用这种方法。。。 这好像是Spring的一个bug,使用Transaction时,只会使用默认的dataSource
(已经由组内其他同事解决了。)

这个问题也可以解决!事务方法的 datasoruce也是可以指定的!
@DataSourceChange 加个属性即可
能说下你们的解决方案不!分享下哈!或者邮件 沟通  jspp@qq.com

相关推荐

Global site tag (gtag.js) - Google Analytics