- 浏览: 307210 次
- 性别:
- 来自: 上海
-
最新评论
-
橙子hhh:
哪有时间给你去研究!!!大神 你时间多
Java获取网络RSS源并使用SAXParser解析 -
a12345531:
...
InputStream为什么不能被重复读取? -
yizishou:
<div class="quote_title ...
谈谈Java的匿名内部类 -
zhangpan1207:
...
InputStream为什么不能被重复读取? -
痴呆患者:
不过受教了 ,不过稍稍修改 还是很好用的 。顶
mybatis如何配置使用多个数据源(environment)?
mybatis如何配置使用多个数据源?
一、数据库连接properties配置文件,两个数据源的地址:
二、mybatis配置文件,配置两个environment:
三、获取SqlSessionFactory,获取Mapper代理,便于在执行完Mapper方法后关闭SqlSession。
SqlSessionFactory的获取:
定义一个统一的Mapper标识接口,每一个具体的Mapper接口继承该接口:
定义一个Mapper代理工厂:
大功告成,客户端使用:
OK,到此基本上所有的工作就完成了,以上的方式就可以支持多个数据源了。
但是代码还不够优雅,以上代码我们发现DataSourceEnvironment这个枚举变量在客户端,MapperFactory以及DataSourceEnvironment
中传来传去,我们应该尽量减少一个类对外界类的耦合,也就是不符合Java编程原则中的迪米特法则。
好了,那我们来改良一下。
将MapperFactory设计成枚举策略模式:
客户端使用场景:
ok,如果大家有什么更优雅的设计方案请不吝分享分享。
不过受教了 ,不过稍稍修改 还是很好用的 。顶
程序还是有BUG
一、数据库连接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
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
4 楼
痴呆患者
2016-04-24
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
![](/images/smiles/icon_biggrin.gif)
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 12279最近在项目中有一个需 ... -
封装使用HttpClient客户端
2014-04-02 14:33 5875HttpClient 是 Apache Jakarta Com ... -
Java 删除html文本中的注释内容
2014-04-01 21:07 3503最近项目中有一个功能 ... -
Java删除html文本中的注释内容
2014-04-01 21:05 2最近项目中有一个功能 ... -
Java程序设计,你属于哪一流派?
2014-03-24 15:19 7035这个话题也是我在程序 ... -
由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理
2014-03-20 00:36 12016最近在用mybatis做项目,需要用到mybatis的拦截器功 ... -
谈谈ThreadLocal和解决线程安全的关系
2014-03-11 02:55 23987在这篇文章中我粗略的就我的理解谈了一下ThreadLocal。 ... -
另一个角度理解java的ThreadLocal
2014-03-09 15:10 7660关于Java的ThreadLocal网上 ... -
谈谈Java的匿名内部类
2014-02-26 23:50 21713在很多时候,我们需要 ... -
通过mark和reset方法重复利用InputStream
2014-02-26 00:24 39756在这篇博客中我们已经 ... -
重复读取InputStream的方法
2014-02-25 23:14 21957在这篇博客中我们已经知道了Java的InputStream是不 ... -
InputStream为什么不能被重复读取?
2014-02-25 21:45 13687首先,熟悉Java的人可能 ...
相关推荐
本文将深入探讨如何在 Spring 中配置和管理多个数据源,并实现动态切换。 首先,我们需要理解“多数据源”是什么。它是指在一个应用中同时连接并操作多个不同的数据库,这些数据库可能具有不同的结构,服务于不同的...
是根元素,<environment>是子元素,可以定义多个。用于配置事务管理,用于配置数据源。 3.3 映射文件 MyBatis的映射文件是xml文件,主要元素包括: * <select>:查询元素 * <insert>:插入元素 * <update>:更新...
总之,MyBatis作为一款强大的ORM框架,其详细设计包括了配置、映射、动态SQL等多个方面,提供了高效、灵活的数据库操作方式,极大地提升了开发效率。在实际项目中,我们需要熟练掌握MyBatis的配置、映射规则以及如何...
`mybatis-config.xml`是MyBatis的全局配置文件,其中包含了数据源、事务管理器等设置。这里是一个基本的配置示例: ```xml <environment id="development"> </environment> ``` 然后...
在Mybatis中,XML配置文件是核心部分,它定义了数据源、事务管理、SqlSessionFactory以及Mapper映射等关键元素。下面我们将深入探讨Mybatis XML配置信息的各个方面。 首先,Mybatis的主配置文件(mybatis-config....
- **environments**:定义了运行时的数据库环境,可以有多个环境配置,如开发、测试和生产环境。 - **environment**:定义单个环境,包括数据源(dataSource)和事务管理器(transactionManager)。 - **...
1. **配置数据源**:首先,我们需要配置多个数据源,例如一个主数据源(用于写操作)和一个或多个从数据源(用于读操作)。这些数据源可以通过Apache的`BasicDataSource`或者其他数据库连接池实现,例如Druid、...
在这里,我们设置了默认环境为“development”,使用JDBC事务管理器,并配置了一个连接池数据源。 2. **映射器配置(Mappers)**:映射器是MyBatis的核心组件,用于将SQL语句与Java接口绑定。有两种方式来配置映射...
其中,你需要指定数据源(dataSource)、事务管理器(transactionManager)以及SqlSessionFactory的配置。例如: ```xml <environment id="development"> </environment> ... ``` 2. *...
- `<dataSource>`:数据源,定义如何获取数据库连接,例如使用POOLED(连接池)或UNPOOLED(非连接池)。 3. **映射文件** - `<mappers>`:该元素用于指定映射文件的位置,这些文件包含了SQL语句和结果映射。 - ...
- **环境(Environment)**:定义了 MyBatis 运行时的环境,包括数据源和事务管理器。 2. **Mapper 映射文件** - **Mapper XML 文件**:包含 SQL 语句和映射规则,每个 Mapper 文件对应一个 Java 接口。 - **@...
这个文件包含了MyBatis的基本设置,如数据源、事务管理器、环境配置等。在配置文件中,我们首先要定义一个`environments`元素,其中包含默认的数据库环境配置。例如: ```xml <environment id="development"> ...
接下来,配置MyBatis的主配置文件`mybatis-config.xml`,包括数据源、事务管理器以及SqlSessionFactory的配置: ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org...
`<environments>`元素用于定义多个环境配置,例如开发环境、测试环境、生产环境等。每个环境都可以指定不同的数据库连接信息、事务管理器等。`default`属性指定了当前环境的默认值。 environment元素 `...
1. **XML配置文件**:MyBatis的初始化配置文件(通常为`mybatis-config.xml`)包含了数据源、事务管理器等全局设置。在这里,你需要指定数据库驱动、连接URL、用户名和密码。例如: ```xml <environment id=...
查询出列表,也就是返回list, 在我们这个例子中也就是 List<User> , 这种方式返回数据,需要在User.xml 里面配置返回的类型 resultMap, 注意不是 resultType, 而这个resultMap 所对应的应该是我们自己配置的 ...
在这个文件中,我们可以定义多个数据源,每个数据源对应一个数据库连接。例如: ```xml <environment id="development"> </environment> <environment id="production"> </...
3. **`environments` 元素**:定义了数据库环境,可以有多个环境配置,如开发、测试和生产环境。 4. **`environment` 元素**:每个环境都有一个 ID,包含 `transactionManager` 和 `dataSource` 子元素,分别用于...
这个最小示例展示了如何配置数据源、创建Mapper接口和XML映射文件,以及如何执行SQL查询。在实际项目中,你可能需要处理更多复杂的操作,如插入、更新和删除数据,以及分页查询等。MyBatis提供了丰富的功能来满足...
这个文件中包含了MyBatis全局配置的所有元素和属性,例如数据源(dataSource)、环境(environment)、事务管理器(transactionManager)、SQL会话工厂(sqlSessionFactory)以及插件(plugins)等。例如,开发者...