Spring Boot + Mybatis多数据源和动态数据源配置方法
网上的文章基本上都是只有多数据源或只有动态数据源,而最近的项目需要同时使用两种方式,记录一下配置方法供大家参考。
应用场景
项目需要同时连接两个不同的数据库a, b,并且它们都为主从架构,一台写库,多台读库。
多数据源
首先要将spring boot自带的datasourceautoconfiguration禁掉,因为它会读取application.properties文件的spring.datasource.*属性并自动配置单数据源。在@springbootapplication注解中添加exclude属性即可:
@springbootapplication(exclude = { datasourceautoconfiguration.class }) public class titanwebapplication { public static void main(string[] args) { springapplication.run(titanwebapplication.class, args); } }
然后在application.properties中配置多数据源连接信息:
# titan库 spring.datasource.titan-master.url=jdbc:mysql://x.x.x.x:port/titan?characterencoding=utf-8 spring.datasource.titan-master.username= spring.datasource.titan-master.password= spring.datasource.titan-master.driver-class-name=com.mysql.jdbc.driver # 连接池配置 # 省略 # 其它库 spring.datasource.db2.url=jdbc:mysql://x.x.x.x:port/titan2?characterencoding=utf-8 spring.datasource.db2.username= spring.datasource.db2.password= spring.datasource.db2.driver-class-name=com.mysql.jdbc.driver
由于我们禁掉了自动数据源配置,因些下一步就需要手动将这些数据源创建出来:
@configuration public class datasourceconfig { @bean(name = "titanmasterds") @configurationproperties(prefix = "spring.datasource.titan-master") // application.properteis中对应属性的前缀 public datasource datasource1() { return datasourcebuilder.create().build(); } @bean(name = "ds2") @configurationproperties(prefix = "spring.datasource.db2") // application.properteis中对应属性的前缀 public datasource datasource2() { return datasourcebuilder.create().build(); } }
接下来需要配置两个mybatis的sqlsessionfactory分别使用不同的数据源:
@configuration @mapperscan(basepackages = {"titan.mapper"}, sqlsessionfactoryref = "sqlsessionfactory1") public class mybatisdbaconfig { @autowired @qualifier("titanmasterds") private datasource ds1; @bean public sqlsessionfactory sqlsessionfactory1() throws exception { sqlsessionfactorybean factorybean = new sqlsessionfactorybean(); factorybean.setdatasource(ds1); // 使用titan数据源, 连接titan库 return factorybean.getobject(); } @bean public sqlsessiontemplate sqlsessiontemplate1() throws exception { sqlsessiontemplate template = new sqlsessiontemplate(sqlsessionfactory1()); // 使用上面配置的factory return template; } }
经过上面的配置后,titan.mapper下的mapper接口,都会使用titan数据源。同理可配第二个sqlsessionfactory:
@configuration @mapperscan(basepackages = {"other.mapper"}, sqlsessionfactoryref = "sqlsessionfactory2") public class mybatisdbbconfig { @autowired @qualifier("ds2") private datasource ds2; @bean public sqlsessionfactory sqlsessionfactory2() throws exception { sqlsessionfactorybean factorybean = new sqlsessionfactorybean(); factorybean.setdatasource(ds2); return factorybean.getobject(); } @bean public sqlsessiontemplate sqlsessiontemplate2() throws exception { sqlsessiontemplate template = new sqlsessiontemplate(sqlsessionfactory2()); return template; } }
完成这些配置后,假设有2个mapper titan.mapper.usermapper和other.mapper.rolemapper,使用前者时会自动连接titan库,后者连接ds2库。
动态数据源
使用动态数据源的初衷,是能在应用层做到读写分离,即在程序代码中控制不同的查询方法去连接不同的库。除了这种方法以外,数据库中间件也是个不错的选择,它的优点是数据库集群对应用来说只暴露为单库,不需要切换数据源的代码逻辑。
我们通过自定义注解 + aop的方式实现数据源动态切换。
首先定义一个contextholder, 用于保存当前线程使用的数据源名:
public class datasourcecontextholder { public static final logger log = loggerfactory.getlogger(datasourcecontextholder.class); /** * 默认数据源 */ public static final string default_ds = "titan-master"; private static final threadlocal<string> contextholder = new threadlocal<>(); // 设置数据源名 public static void setdb(string dbtype) { log.debug("切换到{}数据源", dbtype); contextholder.set(dbtype); } // 获取数据源名 public static string getdb() { return (contextholder.get()); } // 清除数据源名 public static void cleardb() { contextholder.remove(); } }
然后自定义一个javax.sql.datasource接口的实现,这里只需要继承spring为我们预先实现好的父类abstractroutingdatasource即可:
public class dynamicdatasource extends abstractroutingdatasource { private static final logger log = loggerfactory.getlogger(dynamicdatasource.class); @override protected object determinecurrentlookupkey() { log.debug("数据源为{}", datasourcecontextholder.getdb()); return datasourcecontextholder.getdb(); } }
创建动态数据源:
/** * 动态数据源: 通过aop在不同数据源之间动态切换 * @return */ @bean(name = "dynamicds1") public datasource datasource() { dynamicdatasource dynamicdatasource = new dynamicdatasource(); // 默认数据源 dynamicdatasource.setdefaulttargetdatasource(datasource1()); // 配置多数据源 map<object, object> dsmap = new hashmap(5); dsmap.put("titan-master", datasource1()); dsmap.put("ds2", datasource2()); dynamicdatasource.settargetdatasources(dsmap); return dynamicdatasource; }
自定义注释@ds用于在编码时指定方法使用哪个数据源:
@retention(retentionpolicy.runtime) @target({ elementtype.method }) public @interface ds { string value() default "titan-master"; }
编写aop切面,实现切换逻辑:
@aspect @component public class dynamicdatasourceaspect { @before("@annotation(ds)") public void beforeswitchds(joinpoint point){ //获得当前访问的class class<?> classname = point.gettarget().getclass(); //获得访问的方法名 string methodname = point.getsignature().getname(); //得到方法的参数的类型 class[] argclass = ((methodsignature)point.getsignature()).getparametertypes(); string datasource = datasourcecontextholder.default_ds; try { // 得到访问的方法对象 method method = classname.getmethod(methodname, argclass); // 判断是否存在@ds注解 if (method.isannotationpresent(ds.class)) { ds annotation = method.getannotation(ds.class); // 取出注解中的数据源名 datasource = annotation.value(); } } catch (exception e) { e.printstacktrace(); } // 切换数据源 datasourcecontextholder.setdb(datasource); } @after("@annotation(ds)") public void afterswitchds(joinpoint point){ datasourcecontextholder.cleardb(); } }
完成上述配置后,在先前sqlsessionfactory配置中指定使用dynamicdatasource就可以在service中愉快的切换数据源了:
@autowired private useramodelmapper useramapper; @ds("titan-master") public string ds1() { return useramapper.selectbyprimarykey(1).getname(); } @ds("ds2") public string ds2() { return useramapper.selectbyprimarykey(1).getname(); }
总结
以上所述是小编给大家介绍的spring boot + mybatis多数据源和动态数据源配置方法,希望对大家有所帮助
推荐阅读
-
详解Spring Boot + Mybatis 实现动态数据源
-
Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法
-
Spring+Mybatis动态切换数据源的方法
-
Spring Boot + Mybatis多数据源和动态数据源配置方法
-
Spring+Mybatis动态切换数据源的方法
-
spring boot配置MySQL数据库连接、Hikari连接池和Mybatis的简单配置方法
-
Spring Boot 整合mybatis 使用多数据源的实现方法
-
通过Spring Boot配置动态数据源访问多个数据库的实现代码
-
spring整合c3p0整合mybatis。spring使用java配置类来整合配置c3p0数据源和mybatis。
-
bboss与spring中配置和引用bboss数据源和bboss dao组件方法说明