mybatis如何配置使用多个数据源?
出自http://zhangbo-peipei-163-com.iteye.com/blog/2052924
一、数据库连接properties配置文件,两个数据源的地址:
Java代码
- 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代码
- <?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的获取:
Java代码
- /**
- * 根据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接口继承该接口:
Java代码
- /**
- * Mapper Interface
- * @author boyce
- * @version 2014-3-28
- */
- public interface Mapper {
- }
定义一个Mapper代理工厂:
Java代码
- /**
- * 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);
- }
大功告成,客户端使用:
Java代码
- UserMapper mapper = MapperFactory.createMapper(UserMapper.class, DataSourceEnvironment.HD);
- User user = mapper.getUserById(162L);
- System.out.println(user);
OK,到此基本上所有的工作就完成了,以上的方式就可以支持多个数据源了。
但是代码还不够优雅,以上代码我们发现DataSourceEnvironment这个枚举变量在客户端,MapperFactory以及DataSourceEnvironment
中传来传去,我们应该尽量减少一个类对外界类的耦合,也就是不符合Java编程原则中的迪米特法则。
好了,那我们来改良一下。
将MapperFactory设计成枚举策略模式:
Java代码
- /**
- * 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;
- }
- }
- }
客户端使用场景:
Java代码
- UserMapper mapper = MapperFactory.HO.createMapper(UserMapper.class);
- User user = mapper.getUserById(162L);
- System.out.println(user);
ok,如果大家有什么更优雅的设计方案请不吝分享分享。
时间: 2024-11-05 13:29:01