mybatis配置使用多个数据源

mybatis如何配置使用多个数据源?

出自http://zhangbo-peipei-163-com.iteye.com/blog/2052924

一、数据库连接properties配置文件,两个数据源的地址:

Java代码  

  1. hd.jdbc.driverClassName=com.mysql.jdbc.Driver
  2. hd.jdbc.url=jdbc:mysql://127.0.0.1::3306/hd?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
  3. hd.jdbc.username=root
  4. hd.jdbc.password=root
  5. ho.jdbc.driverClassName=com.mysql.jdbc.Driver
  6. ho.jdbc.url=jdbc:mysql://127.0.0.1:3306/ho?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
  7. ho.jdbc.username=root
  8. ho.jdbc.password=root

二、mybatis配置文件,配置两个environment:

Xml代码  

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4. <configuration>
  5. <properties resource="mybatis/jdbc.properties"/>
  6. <environments default="HO">
  7. <environment id="HD">
  8. <transactionManager type="JDBC" />
  9. <dataSource type="POOLED">
  10. <property name="driver" value="${hd.jdbc.driverClassName}" />
  11. <property name="url" value="${hd.jdbc.url}" />
  12. <property name="username" value="${hd.jdbc.username}" />
  13. <property name="password" value="${hd.jdbc.password}" />
  14. </dataSource>
  15. </environment>
  16. <environment id="HO">
  17. <transactionManager type="JDBC" />
  18. <dataSource type="POOLED">
  19. <property name="driver" value="${ho.jdbc.driverClassName}" />
  20. <property name="url" value="${ho.jdbc.url}" />
  21. <property name="username" value="${ho.jdbc.username}" />
  22. <property name="password" value="${ho.jdbc.password}" />
  23. </dataSource>
  24. </environment>
  25. </environments>
  26. </configuration>

三、获取SqlSessionFactory,获取Mapper代理,便于在执行完Mapper方法后关闭SqlSession。

SqlSessionFactory的获取:

Java代码  

  1. /**
  2. * 根据mybatis.xml中配置的不同的environment创建对应的SqlSessionFactory
  3. * @author boyce
  4. * @version 2014-3-27
  5. */
  6. public final class DataSourceSqlSessionFactory {
  7. private static final String CONFIGURATION_PATH = "mybatis/mybatis.xml";
  8. private static final Map<DataSourceEnvironment, SqlSessionFactory> SQLSESSIONFACTORYS
  9. = new HashMap<DataSourceEnvironment, SqlSessionFactory>();
  10. /**
  11. * 根据指定的DataSourceEnvironment获取对应的SqlSessionFactory
  12. * @param environment 数据源environment
  13. * @return SqlSessionFactory
  14. */
  15. public static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) {
  16. SqlSessionFactory sqlSessionFactory = SQLSESSIONFACTORYS.get(environment);
  17. if (ObjectUtils.isNotNull(sqlSessionFactory))
  18. return sqlSessionFactory;
  19. else {
  20. InputStream inputStream = null;
  21. try {
  22. inputStream = Resources.getResourceAsStream(CONFIGURATION_PATH);
  23. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, environment.name());
  24. logger.info("Get {} SqlSessionFactory successfully.", environment.name());
  25. } catch (IOException e) {
  26. logger.warn("Get {} SqlSessionFactory error.", environment.name());
  27. logger.error(e.getMessage(), e);
  28. }
  29. finally {
  30. IOUtils.closeQuietly(inputStream);
  31. }
  32. SQLSESSIONFACTORYS.put(environment, sqlSessionFactory);
  33. return sqlSessionFactory;
  34. }
  35. }
  36. /**
  37. * 配置到Configuration.xml文件中的数据源的environment的枚举描述
  38. * @author boyce
  39. * @version 2014-3-27
  40. */
  41. public static enum DataSourceEnvironment {
  42. HD,
  43. HO;
  44. }
  45. }

定义一个统一的Mapper标识接口,每一个具体的Mapper接口继承该接口:

Java代码  

  1. /**
  2. * Mapper Interface
  3. * @author boyce
  4. * @version 2014-3-28
  5. */
  6. public interface Mapper {
  7. }

定义一个Mapper代理工厂:

Java代码  

  1. /**
  2. * Mapper Factory
  3. * @author boyce
  4. * @version 2014-3-28
  5. */
  6. public final class MapperFactory {
  7. private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MapperFactory.class);
  8. /**
  9. * Create a mapper of environment by Mapper class
  10. * @param clazz Mapper class
  11. * @param environment A datasource environment
  12. * @return a Mapper instance
  13. */
  14. @SuppressWarnings("unchecked")
  15. public static <T> T createMapper(Class<? extends Mapper> clazz, DataSourceEnvironment environment) {
  16. SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(environment);
  17. SqlSession sqlSession = sqlSessionFactory.openSession();
  18. Mapper mapper = sqlSession.getMapper(clazz);
  19. return (T)MapperProxy.bind(mapper, sqlSession);
  20. }
  21. /**
  22. * Mapper Proxy
  23. * executing mapper method and close sqlsession
  24. * @author boyce
  25. * @version 2014-4-9
  26. */
  27. private static class MapperProxy implements InvocationHandler {
  28. private Mapper mapper;
  29. private SqlSession sqlSession;
  30. private MapperProxy(Mapper mapper, SqlSession sqlSession) {
  31. this.mapper = mapper;
  32. this.sqlSession = sqlSession;
  33. }
  34. @SuppressWarnings("unchecked")
  35. private static Mapper bind(Mapper mapper, SqlSession sqlSession) {
  36. return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(),
  37. mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession));
  38. }
  39. /**
  40. * execute mapper method and finally close sqlSession
  41. */
  42. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  43. Object object = null;
  44. try {
  45. object = method.invoke(mapper, args);
  46. } catch(Exception e) {
  47. e.printStackTrace();
  48. logger.error(e.getMessage(), e);
  49. } finally {
  50. sqlSession.close();
  51. }
  52. return object;
  53. }
  54. }
  55. //Get a SqlSessionFactory of environment
  56. private static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) {
  57. return DataSourceSqlSessionFactory.getSqlSessionFactory(environment);
  58. }

大功告成,客户端使用:

Java代码  

  1. UserMapper mapper = MapperFactory.createMapper(UserMapper.class, DataSourceEnvironment.HD);
  2. User user = mapper.getUserById(162L);
  3. System.out.println(user);

OK,到此基本上所有的工作就完成了,以上的方式就可以支持多个数据源了。

但是代码还不够优雅,以上代码我们发现DataSourceEnvironment这个枚举变量在客户端,MapperFactory以及DataSourceEnvironment

中传来传去,我们应该尽量减少一个类对外界类的耦合,也就是不符合Java编程原则中的迪米特法则。

好了,那我们来改良一下。

将MapperFactory设计成枚举策略模式:

Java代码  

  1. /**
  2. * Mapper Creator
  3. * @author boyce
  4. * @version 2014-3-28
  5. */
  6. public enum MapperFactory {
  7. HD {
  8. private SqlSessionFactory sqlSessionFactory;
  9. @Override
  10. public <T> T createMapper(Class<? extends Mapper> clazz) {
  11. return createMapper(clazz, this);
  12. }
  13. @Override
  14. protected void createSqlSessionFactory() {
  15. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name());
  16. }
  17. @Override
  18. public SqlSessionFactory getSqlSessionFactory() {
  19. return sqlSessionFactory;
  20. }
  21. },
  22. HO {
  23. private SqlSessionFactory sqlSessionFactory;
  24. @Override
  25. public <T> T createMapper(Class<? extends Mapper> clazz) {
  26. return createMapper(clazz, this);
  27. }
  28. @Override
  29. protected void createSqlSessionFactory() {
  30. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name());
  31. }
  32. @Override
  33. public SqlSessionFactory getSqlSessionFactory() {
  34. return sqlSessionFactory;
  35. }
  36. };
  37. /**
  38. * Create a mapper of environment by Mapper class
  39. * @param clazz Mapper class
  40. * @param environment A datasource environment
  41. * @return a Mapper instance
  42. */
  43. public abstract <T> T createMapper(Class<? extends Mapper> clazz);
  44. /**
  45. * Create SqlSessionFactory of environment
  46. */
  47. protected abstract void createSqlSessionFactory();
  48. /**
  49. * get SqlSessionFactory
  50. */
  51. public abstract SqlSessionFactory getSqlSessionFactory();
  52. private static InputStream inputStream = null;
  53. static {
  54. try {
  55. inputStream = Resources.getResourceAsStream("mybatis/mybatis.xml");
  56. HO.createSqlSessionFactory();
  57. HD.createSqlSessionFactory();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. } finally {
  61. IOUtils.closeQuietly(inputStream);
  62. }
  63. }
  64. @SuppressWarnings("unchecked")
  65. private static <T> T createMapper(Class<? extends Mapper> clazz, MapperFactory MapperFactory) {
  66. SqlSession sqlSession = MapperFactory.getSqlSessionFactory().openSession();
  67. Mapper mapper = sqlSession.getMapper(clazz);
  68. return (T)MapperProxy.bind(mapper, sqlSession);
  69. }
  70. /**
  71. * Mapper Proxy
  72. * executing mapper method and close sqlsession
  73. * @author boyce
  74. * @version 2014-4-9
  75. */
  76. private static class MapperProxy implements InvocationHandler {
  77. private Mapper mapper;
  78. private SqlSession sqlSession;
  79. private MapperProxy(Mapper mapper, SqlSession sqlSession) {
  80. this.mapper = mapper;
  81. this.sqlSession = sqlSession;
  82. }
  83. private static Mapper bind(Mapper mapper, SqlSession sqlSession) {
  84. return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(),
  85. mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession));
  86. }
  87. /**
  88. * execute mapper method and finally close sqlSession
  89. */
  90. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  91. Object object = null;
  92. try {
  93. object = method.invoke(mapper, args);
  94. } catch(Exception e) {
  95. e.printStackTrace();
  96. } finally {
  97. sqlSession.close();
  98. }
  99. return object;
  100. }
  101. }
  102. }

客户端使用场景:

Java代码  

  1. UserMapper mapper = MapperFactory.HO.createMapper(UserMapper.class);
  2. User user = mapper.getUserById(162L);
  3. System.out.println(user);

ok,如果大家有什么更优雅的设计方案请不吝分享分享。

时间: 2024-11-05 13:29:01

mybatis配置使用多个数据源的相关文章

MyBatis配置数据源的两种方式

---------------------siwuxie095 MyBatis 配置数据源的两种方式 1.配置方式一:配置数据库连接信息到核心配置文件中 在 mybatis-config.xml 中添加如下内容: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" &

SpringBoot+Druid+Mybatis配置多数据源

我们在开发一个项目的时候,可能会遇到需要对多个数据库进行读写的需求,这时候就得在项目中配置多个数据源了.在Java项目的开发中,目前最常用的数据操作框架是 Mybatis,开发框架也都基本用上了SpringBoot.而Druid号称最好的数据库连接池,自然也是被广泛使用. 所以本文将演示一下,SpringBoot+Druid+Mybatis如何去配置多数据源.首先在IDEA中创建一个SpringBoot工程: 选择一些基本的包: 完成创建: pom.xml配置的依赖如下: <dependenci

Spring 数据源配置二:多数据源

通过上一节  Spring 数据源配置一: 单一数据源  我们了解单一数据源的配置, 这里我们继续多个数据源的配置 如下(applicationContent.xml 内容) 一:  Spring  配置: <!-- MYSQL 配置 --> <bean id="mysqlDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <p

springboot mybatis 优雅的添加多数据源

springboot的原则是简化配置,本文试图不通过xml配置,使用configuration配置数据源,并进行简单的数据访问. 并且配置了多数据源,在开发过程中这种场景很容易遇到. 1.依赖 springboot的starter mybatis的springboot集成包 jdbc <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g

Spring + Mybatis 项目实现动态切换数据源

项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. 参考了两篇文章如下: http://blog.csdn.net/zl3450341/article/details/20150687 http://www.blogjava.net/hoojo/archive/2013/10/22/405488.html 这两篇文章都对原理进行了分析,下面只写自己

spring mvc+mybatis配置多数据源文件

spring-db-context.xml: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.

Mybatis配置问题解决Invalid bound statement (not found)

首先这个异常的原因是系统根据Mapper类的方法名找不到对应的映射文件. 网上也搜索了到了类似的文章,一般可以从以下几个点排查: mapper.xml的namespace要写所映射接口的全称类名,而且要和Mapper类对应好! mapper.xml中的每个statement的id要和接口方法的方法名相同 mapper.xml中定义的每个sql的parameterType要和接口方法的形参类型相同 mapper.xml中定义的每个sql的resultType要和接口方法的返回值的类型相同 mapp

SpringBoot+Mybatis+ Druid+PageHelper 实现多数据源并分页

前言 本篇文章主要讲述的是SpringBoot整合Mybatis.Druid和PageHelper 并实现多数据源和分页.其中SpringBoot整合Mybatis这块,在之前的的一篇文章中已经讲述了,这里就不过多说明了.重点是讲述在多数据源下的如何配置使用Druid和PageHelper . Druid介绍和使用 在使用Druid之前,先来简单的了解下Druid. Druid是一个数据库连接池.Druid可以说是目前最好的数据库连接池!因其优秀的功能.性能和扩展性方面,深受开发人员的青睐.Dr

MyBatis配置总结

参考:<JavaEE 互联网轻量级框架整合开发>-第 4 章 一.配置概述 <configuration><!--配置--> <properties></properties><!--属性--> <settings></settings><!--设置--> <typeAliases></typeAliases><!--类型命名--> <typeHandler