mybatis如何配置使用多个数据源(environment)

来源:互联网 发布:方象餐饮软件 编辑:程序博客网 时间:2024/04/27 15:22
mybatis如何配置使用多个数据源? 
一、数据库连接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.   
  6. ho.jdbc.driverClassName=com.mysql.jdbc.Driver  
  7. ho.jdbc.url=jdbc:mysql://127.0.0.1:3306/ho?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true  
  8. ho.jdbc.username=root  
  9. 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.       
  9.     private static final Map<DataSourceEnvironment, SqlSessionFactory> SQLSESSIONFACTORYS   
  10.         = new HashMap<DataSourceEnvironment, SqlSessionFactory>();  
  11.       
  12.     /** 
  13.      * 根据指定的DataSourceEnvironment获取对应的SqlSessionFactory 
  14.      * @param environment 数据源environment 
  15.      * @return SqlSessionFactory 
  16.      */  
  17.     public static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) {  
  18.           
  19.         SqlSessionFactory sqlSessionFactory = SQLSESSIONFACTORYS.get(environment);  
  20.         if (ObjectUtils.isNotNull(sqlSessionFactory))  
  21.             return sqlSessionFactory;  
  22.         else {  
  23.             InputStream inputStream = null;  
  24.             try {  
  25.                 inputStream = Resources.getResourceAsStream(CONFIGURATION_PATH);  
  26.                 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, environment.name());  
  27.                   
  28.                 logger.info("Get {} SqlSessionFactory successfully.", environment.name());  
  29.             } catch (IOException e) {  
  30.                 logger.warn("Get {} SqlSessionFactory error.", environment.name());  
  31.                 logger.error(e.getMessage(), e);  
  32.             }  
  33.             finally {  
  34.                 IOUtils.closeQuietly(inputStream);  
  35.             }  
  36.               
  37.             SQLSESSIONFACTORYS.put(environment, sqlSessionFactory);  
  38.             return sqlSessionFactory;  
  39.         }  
  40.     }  
  41.       
  42.     /** 
  43.      * 配置到Configuration.xml文件中的数据源的environment的枚举描述 
  44.      * @author boyce 
  45.      * @version 2014-3-27 
  46.      */  
  47.     public static enum DataSourceEnvironment {  
  48.         HD,  
  49.         HO;  
  50.     }  
  51. }  


定义一个统一的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.     /** 
  23.      * Mapper Proxy  
  24.      * executing mapper method and close sqlsession 
  25.      * @author boyce 
  26.      * @version 2014-4-9 
  27.      */  
  28.     private static class MapperProxy implements InvocationHandler {  
  29.         private Mapper mapper;  
  30.         private SqlSession sqlSession;  
  31.           
  32.         private MapperProxy(Mapper mapper, SqlSession sqlSession) {  
  33.             this.mapper = mapper;  
  34.             this.sqlSession = sqlSession;  
  35.         }  
  36.           
  37.         @SuppressWarnings("unchecked")  
  38.         private static Mapper bind(Mapper mapper, SqlSession sqlSession) {  
  39.             return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(),  
  40.                     mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession));  
  41.         }  
  42.   
  43.         /** 
  44.          * execute mapper method and finally close sqlSession 
  45.          */  
  46.         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  47.             Object object = null;  
  48.             try {  
  49.                 object = method.invoke(mapper, args);  
  50.             } catch(Exception e) {  
  51.                 e.printStackTrace();  
  52.                 logger.error(e.getMessage(), e);  
  53.             } finally {  
  54.                 sqlSession.close();  
  55.             }  
  56.             return object;  
  57.         }  
  58.     }  
  59.       
  60.     //Get a SqlSessionFactory of environment  
  61.     private static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) {  
  62.         return DataSourceSqlSessionFactory.getSqlSessionFactory(environment);  
  63.     }  

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

客户端使用场景: 
Java代码  收藏代码
  1. UserMapper mapper = MapperFactory.HO.createMapper(UserMapper.class);  
  2. User user = mapper.getUserById(162L);  
  3. System.out.println(user);  

ok,如果大家有什么更优雅的设计方案请不吝分享分享。
0 0
原创粉丝点击