mybatis配置使用多个数据源

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

来源:zhanjianshinian的专栏 

一、数据库连接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,如果大家有什么更优雅的设计方案请不吝分享分享。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值