假设现在有两个数据库myone和mytwo,读者可以理解为一个写库,一个读库,数据库中都各自有一个表,表的格式都一样,如下:
------------------------------------------------------------
id int(11) PRI auto_increment
username varchar(20)
password varchar(20)
------------------------------------------------------------
数据库脚本如下:
create database myone;
use myone;
create table user(id int auto_increment primary key,username varchar(20),password varchar(20));
create database mytwo;
use mytwo;
create table user(id int auto_increment primary key,username varchar(20),password varchar(20));
insert into mytwo.user(username,password) value('test','test');
现在想要实现数据库的自动切换,有些mapper操作写库myone,有些mapper操作读库mytwo。
首先,构建maven工程,pom文件如下:
4.0.0
com.aliyun.security
resourcegroup
1.0-SNAPSHOT
org.apache.commons
commons-dbcp2
2.1.1
org.mybatis
mybatis
3.2.8
org.springframework
spring-jdbc
4.1.6.RELEASE
org.springframework
spring-aop
4.1.6.RELEASE
org.springframework
spring-context
4.1.6.RELEASE
org.aspectj
aspectjweaver
1.8.6
org.mybatis
mybatis-spring
1.1.1
mysql
mysql-connector-java
5.1.38
接下来是写库myone对应的mapper,如下:
package dal.mapper.myone;
import dal.dataobject.myone.User;
public interface OneUserManageMapper {
int createUser(User user);
}
INSERT INTO user(username, password) VALUES(#{username}, #{password})
接下来是读库mytwo对应的mapper,如下:
package dal.mapper.mytwo;
import dal.dataobject.mytwo.User;
import org.apache.ibatis.annotations.Param;
public interface TwoUserManageMapper {
User getUserById(@Param("id") int id);
}
接下来是实现自动切换最主要的代码,这里使用AOP编程来实现:
package dal.datasourceswitch;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* Created by Administrator on 2016/8/22.
*/
/**
* Created by rabbit on 14-5-25.
*/
public class MultipleDataSource extends AbstractRoutingDataSource {
private static ThreadLocal threadLocalDatasource=new ThreadLocal(){
@Override
protected String initialValue() {
return null;
}
};
public static void setThreadLocalDatasource(String dsName){
threadLocalDatasource.set(dsName);
}
@Override
protected Object determineCurrentLookupKey() {
return threadLocalDatasource.get();
}
}
package dal.datasourceswitch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MultipleDataSourceAspectAdvice {
@Around("execution(* dal.mapper.myone..*.*(*))")
public Object doAround1(ProceedingJoinPoint jp) throws Throwable {
MultipleDataSource.setThreadLocalDatasource("myone");
return jp.proceed();
}
@Around("execution(* dal.mapper.mytwo..*.*(*))")
public Object doAround2(ProceedingJoinPoint jp) throws Throwable {
MultipleDataSource.setThreadLocalDatasource("mytwo");
return jp.proceed();
}
}
读者可以学习下AbstractRoutingDataSource类,就知道这么做的理由了。
最后,看下spring的配置文件:
jdbc.properties
mapper/OneUserManageMapper.xml
mapper/TwoUserManageMapper.xml
上面是实现多数据源自动切换的主要代码,源码github地址:
https://github.com/ZhenShiErGe/Multi-Datasource-Autoswitch.git
文章修改自http://www.cnblogs.com/lzrabbit/p/3750803.html
到知乎阅读最新的技术博客:https://www.zhihu.com/people/hulianwangzhaopin/activities
提供给想学习云计算的同学,欢迎收听https://www.zhihu.com/lives/1046567982750281728
笔者开设了一个知乎live,详细的介绍的JAVA从入门到精通该如何学,学什么?
提供给想深入学习和提高JAVA能力的同学,欢迎收听https://www.zhihu.com/lives/932192204248682496