- 浏览: 306180 次
- 性别:
- 来自: 上海
最新评论
-
橙子hhh:
哪有时间给你去研究!!!大神 你时间多
Java获取网络RSS源并使用SAXParser解析 -
a12345531:
...
InputStream为什么不能被重复读取? -
yizishou:
引用另一方面当串行化这个子类实例时外部类也会被不知不觉的串行化 ...
谈谈Java的匿名内部类 -
zhangpan1207:
...
InputStream为什么不能被重复读取? -
痴呆患者:
不过受教了 ,不过稍稍修改 还是很好用的 。顶
mybatis如何配置使用多个数据源(environment)?
mybatis如何配置使用多个数据源?
一、数据库连接properties配置文件,两个数据源的地址:
二、mybatis配置文件,配置两个environment:
三、获取SqlSessionFactory,获取Mapper代理,便于在执行完Mapper方法后关闭SqlSession。
SqlSessionFactory的获取:
定义一个统一的Mapper标识接口,每一个具体的Mapper接口继承该接口:
定义一个Mapper代理工厂:
大功告成,客户端使用:
OK,到此基本上所有的工作就完成了,以上的方式就可以支持多个数据源了。
但是代码还不够优雅,以上代码我们发现DataSourceEnvironment这个枚举变量在客户端,MapperFactory以及DataSourceEnvironment
中传来传去,我们应该尽量减少一个类对外界类的耦合,也就是不符合Java编程原则中的迪米特法则。
好了,那我们来改良一下。
将MapperFactory设计成枚举策略模式:
客户端使用场景:
ok,如果大家有什么更优雅的设计方案请不吝分享分享。
一、数据库连接properties配置文件,两个数据源的地址:
hd.jdbc.driverClassName=com.mysql.jdbc.Driver hd.jdbc.url=jdbc:mysql://127.0.0.1::3306/hd?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true hd.jdbc.username=root hd.jdbc.password=root ho.jdbc.driverClassName=com.mysql.jdbc.Driver ho.jdbc.url=jdbc:mysql://127.0.0.1:3306/ho?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true ho.jdbc.username=root ho.jdbc.password=root
二、mybatis配置文件,配置两个environment:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="mybatis/jdbc.properties"/> <environments default="HO"> <environment id="HD"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${hd.jdbc.driverClassName}" /> <property name="url" value="${hd.jdbc.url}" /> <property name="username" value="${hd.jdbc.username}" /> <property name="password" value="${hd.jdbc.password}" /> </dataSource> </environment> <environment id="HO"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${ho.jdbc.driverClassName}" /> <property name="url" value="${ho.jdbc.url}" /> <property name="username" value="${ho.jdbc.username}" /> <property name="password" value="${ho.jdbc.password}" /> </dataSource> </environment> </environments> </configuration>
三、获取SqlSessionFactory,获取Mapper代理,便于在执行完Mapper方法后关闭SqlSession。
SqlSessionFactory的获取:
/** * 根据mybatis.xml中配置的不同的environment创建对应的SqlSessionFactory * @author boyce * @version 2014-3-27 */ public final class DataSourceSqlSessionFactory { private static final String CONFIGURATION_PATH = "mybatis/mybatis.xml"; private static final Map<DataSourceEnvironment, SqlSessionFactory> SQLSESSIONFACTORYS = new HashMap<DataSourceEnvironment, SqlSessionFactory>(); /** * 根据指定的DataSourceEnvironment获取对应的SqlSessionFactory * @param environment 数据源environment * @return SqlSessionFactory */ public static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) { SqlSessionFactory sqlSessionFactory = SQLSESSIONFACTORYS.get(environment); if (ObjectUtils.isNotNull(sqlSessionFactory)) return sqlSessionFactory; else { InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(CONFIGURATION_PATH); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, environment.name()); logger.info("Get {} SqlSessionFactory successfully.", environment.name()); } catch (IOException e) { logger.warn("Get {} SqlSessionFactory error.", environment.name()); logger.error(e.getMessage(), e); } finally { IOUtils.closeQuietly(inputStream); } SQLSESSIONFACTORYS.put(environment, sqlSessionFactory); return sqlSessionFactory; } } /** * 配置到Configuration.xml文件中的数据源的environment的枚举描述 * @author boyce * @version 2014-3-27 */ public static enum DataSourceEnvironment { HD, HO; } }
定义一个统一的Mapper标识接口,每一个具体的Mapper接口继承该接口:
/** * Mapper Interface * @author boyce * @version 2014-3-28 */ public interface Mapper { }
定义一个Mapper代理工厂:
/** * Mapper Factory * @author boyce * @version 2014-3-28 */ public final class MapperFactory { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MapperFactory.class); /** * Create a mapper of environment by Mapper class * @param clazz Mapper class * @param environment A datasource environment * @return a Mapper instance */ @SuppressWarnings("unchecked") public static <T> T createMapper(Class<? extends Mapper> clazz, DataSourceEnvironment environment) { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(environment); SqlSession sqlSession = sqlSessionFactory.openSession(); Mapper mapper = sqlSession.getMapper(clazz); return (T)MapperProxy.bind(mapper, sqlSession); } /** * Mapper Proxy * executing mapper method and close sqlsession * @author boyce * @version 2014-4-9 */ private static class MapperProxy implements InvocationHandler { private Mapper mapper; private SqlSession sqlSession; private MapperProxy(Mapper mapper, SqlSession sqlSession) { this.mapper = mapper; this.sqlSession = sqlSession; } @SuppressWarnings("unchecked") private static Mapper bind(Mapper mapper, SqlSession sqlSession) { return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(), mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession)); } /** * execute mapper method and finally close sqlSession */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object = null; try { object = method.invoke(mapper, args); } catch(Exception e) { e.printStackTrace(); logger.error(e.getMessage(), e); } finally { sqlSession.close(); } return object; } } //Get a SqlSessionFactory of environment private static SqlSessionFactory getSqlSessionFactory(DataSourceEnvironment environment) { return DataSourceSqlSessionFactory.getSqlSessionFactory(environment); }
大功告成,客户端使用:
UserMapper mapper = MapperFactory.createMapper(UserMapper.class, DataSourceEnvironment.HD); User user = mapper.getUserById(162L); System.out.println(user);
OK,到此基本上所有的工作就完成了,以上的方式就可以支持多个数据源了。
但是代码还不够优雅,以上代码我们发现DataSourceEnvironment这个枚举变量在客户端,MapperFactory以及DataSourceEnvironment
中传来传去,我们应该尽量减少一个类对外界类的耦合,也就是不符合Java编程原则中的迪米特法则。
好了,那我们来改良一下。
将MapperFactory设计成枚举策略模式:
/** * Mapper Creator * @author boyce * @version 2014-3-28 */ public enum MapperFactory { HD { private SqlSessionFactory sqlSessionFactory; @Override public <T> T createMapper(Class<? extends Mapper> clazz) { return createMapper(clazz, this); } @Override protected void createSqlSessionFactory() { sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name()); } @Override public SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } }, HO { private SqlSessionFactory sqlSessionFactory; @Override public <T> T createMapper(Class<? extends Mapper> clazz) { return createMapper(clazz, this); } @Override protected void createSqlSessionFactory() { sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, this.name()); } @Override public SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } }; /** * Create a mapper of environment by Mapper class * @param clazz Mapper class * @param environment A datasource environment * @return a Mapper instance */ public abstract <T> T createMapper(Class<? extends Mapper> clazz); /** * Create SqlSessionFactory of environment */ protected abstract void createSqlSessionFactory(); /** * get SqlSessionFactory */ public abstract SqlSessionFactory getSqlSessionFactory(); private static InputStream inputStream = null; static { try { inputStream = Resources.getResourceAsStream("mybatis/mybatis.xml"); HO.createSqlSessionFactory(); HD.createSqlSessionFactory(); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(inputStream); } } @SuppressWarnings("unchecked") private static <T> T createMapper(Class<? extends Mapper> clazz, MapperFactory MapperFactory) { SqlSession sqlSession = MapperFactory.getSqlSessionFactory().openSession(); Mapper mapper = sqlSession.getMapper(clazz); return (T)MapperProxy.bind(mapper, sqlSession); } /** * Mapper Proxy * executing mapper method and close sqlsession * @author boyce * @version 2014-4-9 */ private static class MapperProxy implements InvocationHandler { private Mapper mapper; private SqlSession sqlSession; private MapperProxy(Mapper mapper, SqlSession sqlSession) { this.mapper = mapper; this.sqlSession = sqlSession; } private static Mapper bind(Mapper mapper, SqlSession sqlSession) { return (Mapper) Proxy.newProxyInstance(mapper.getClass().getClassLoader(), mapper.getClass().getInterfaces(), new MapperProxy(mapper, sqlSession)); } /** * execute mapper method and finally close sqlSession */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object object = null; try { object = method.invoke(mapper, args); } catch(Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } return object; } } }
客户端使用场景:
UserMapper mapper = MapperFactory.HO.createMapper(UserMapper.class); User user = mapper.getUserById(162L); System.out.println(user);
ok,如果大家有什么更优雅的设计方案请不吝分享分享。
评论
5 楼
痴呆患者
2016-04-24
不过受教了 ,不过稍稍修改 还是很好用的 。顶
4 楼
痴呆患者
2016-04-24
程序还是有BUG
3 楼
alreadyfor
2014-10-29
Mapper类?
2 楼
lf78204490
2014-07-23
sqlSession.commit(),怎么执行啊?
1 楼
touloveyan
2014-04-23
可以使用spring的动态数据源
发表评论
-
Java获取网络RSS源并使用SAXParser解析
2014-04-02 15:48 12232最近在项目中有一个需 ... -
封装使用HttpClient客户端
2014-04-02 14:33 5830HttpClient 是 Apache Jakarta Com ... -
Java 删除html文本中的注释内容
2014-04-01 21:07 3472最近项目中有一个功能 ... -
Java删除html文本中的注释内容
2014-04-01 21:05 2最近项目中有一个功能 ... -
Java程序设计,你属于哪一流派?
2014-03-24 15:19 6994这个话题也是我在程序 ... -
由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理
2014-03-20 00:36 11973最近在用mybatis做项目,需要用到mybatis的拦截器功 ... -
谈谈ThreadLocal和解决线程安全的关系
2014-03-11 02:55 23933在这篇文章中我粗略的就我的理解谈了一下ThreadLocal。 ... -
另一个角度理解java的ThreadLocal
2014-03-09 15:10 7609关于Java的ThreadLocal网上 ... -
谈谈Java的匿名内部类
2014-02-26 23:50 21679在很多时候,我们需要 ... -
通过mark和reset方法重复利用InputStream
2014-02-26 00:24 39678在这篇博客中我们已经 ... -
重复读取InputStream的方法
2014-02-25 23:14 21893在这篇博客中我们已经知道了Java的InputStream是不 ... -
InputStream为什么不能被重复读取?
2014-02-25 21:45 13644首先,熟悉Java的人可能 ...
相关推荐
springboot +mybatis+oracle 配置多个数据源,配置两个数据库信息
主要介绍了Spring3 整合MyBatis3 配置多数据源动态选择SqlSessionFactory详细教程,需要的朋友可以参考下
SSM(Spring+SpringMVC+MyBatis)多数据源配置框架,精简版
SpringBoot整合mybatis-plus实现多数据源的动态切换且支持分页查询,案例以postgresql和oracle数据库为数据源,分别使用mybatis-plus分页插件和pagehelper分页插件实现分页查询。
springboot整合mybatis配置多数据源
SpringMVC+Mybatis(多数据源)+Mongo(多数据源),框架适合同时访问多种DB,且支持每种DB配置多个数据源。正如我代码中的demo,配置了两个mysql数据源+2个mongo数据源,可以在service实现中随意访问。除此之外还通过...
mybatis-plus 多数据源/动态数据源配置示例代码
mybatis-plus+动态数据源+自定义数据源配置+dom解析+自定义参数注入(注解)+AOP切换数据源+druid
分布式,mybatis-plus,多数据源总结分布式,mybatis-plus,多数据源总结
多数据源配置,使用了数据库连接池,并且是多数据源,分也不要多了,2分,有什么疑问可以指出,或者不足也可以一起学习
springboot+mybatis多数据源+动态数据源配置(连接池),mysql数据库,代码实现了简单的读写分离,但是不建议这种操作,建议使用数据库中间件进行读写分离,例如使用mycat进行读写分离主从热备,使用该代码对于多个...
pringMVC +Mybatis 多个数据源配置 DEMO + maven,利用AbstractDataSource抽象化完成多了个数据源的配置
SpringBoot+gradle+mybatis多数据源动态配置 AOP的方式实现数据源动态切换。
解压后有资源文件和说明文件 需要创建两个数据库 名字为: familymonitor_v2 和 orderpayment ... 表tb_coupon_info 在数据库orderpayment 中 ...环境为 spring boot mybatis +多数据源 demosql.sql为数据库建表语句
一个注解搞定的MyBatis多数据源,当前个人思考的最好的多数据源方案,灵活性较强,可自主选择指定数据源。
Springboot2.7.0 + mybatis 搭建多数据源
spring boot 2多数据源,里面有hibernate和mybatis的多数据源代码。代码拿过去即可集成使用。
spring+mybatis 多个数据源调用示例
Springboot mybatis 多数据源配置 项目实例·················
mybatis+spring实现动态切换数据源,修改数据源配置信息之后,直接运行test可进行测试