`
该用户名已经存在
  • 浏览: 308313 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多
mybatis如何配置使用多个数据源?
一、数据库连接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,如果大家有什么更优雅的设计方案请不吝分享分享。
4
1
分享到:
评论
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的动态数据源

相关推荐

    spring mybatis 多数据源动态切换

    本文将深入探讨如何在 Spring 中配置和管理多个数据源,并实现动态切换。 首先,我们需要理解“多数据源”是什么。它是指在一个应用中同时连接并操作多个不同的数据库,这些数据库可能具有不同的结构,服务于不同的...

    第三章 MyBatis的核心配置.docx

    是根元素,&lt;environment&gt;是子元素,可以定义多个。用于配置事务管理,用于配置数据源。 3.3 映射文件 MyBatis的映射文件是xml文件,主要元素包括: * &lt;select&gt;:查询元素 * &lt;insert&gt;:插入元素 * &lt;update&gt;:更新...

    mybatis、mybatis详细设计、mybatis配置

    总之,MyBatis作为一款强大的ORM框架,其详细设计包括了配置、映射、动态SQL等多个方面,提供了高效、灵活的数据库操作方式,极大地提升了开发效率。在实际项目中,我们需要熟练掌握MyBatis的配置、映射规则以及如何...

    mybatis简单使用xml配置的Demo

    `mybatis-config.xml`是MyBatis的全局配置文件,其中包含了数据源、事务管理器等设置。这里是一个基本的配置示例: ```xml &lt;environment id="development"&gt; &lt;/environment&gt; ``` 然后...

    基于MyBatis XML配置方法(全面了解)

    MyBatis的配置文件包含了多个元素,包括settings、properties、typeAliases、typeHandlers、objectFactory、plugins、environments、environment、transactionManager、dataSource、databaseIdProvider和mappers等。...

    Mybatis XML配置信息说明

    在Mybatis中,XML配置文件是核心部分,它定义了数据源、事务管理、SqlSessionFactory以及Mapper映射等关键元素。下面我们将深入探讨Mybatis XML配置信息的各个方面。 首先,Mybatis的主配置文件(mybatis-config....

    Mybatis-3.2.7 jar包sqConf.xml ,MybatisConfig.xml主方法配置

    - **environments**:定义了运行时的数据库环境,可以有多个环境配置,如开发、测试和生产环境。 - **environment**:定义单个环境,包括数据源(dataSource)和事务管理器(transactionManager)。 - **...

    mybaties切换数据源.rar

    1. **配置数据源**:首先,我们需要配置多个数据源,例如一个主数据源(用于写操作)和一个或多个从数据源(用于读操作)。这些数据源可以通过Apache的`BasicDataSource`或者其他数据库连接池实现,例如Druid、...

    MyBatis配置dad的方式

    - `&lt;environment&gt;`元素可以配置多个,每个对应一个不同的环境。 5. **`&lt;transactionManager&gt;`元素**: - 配置事务管理器。 - `type`属性可以设置为“JDBC”或“MANAGED”。 6. **`&lt;dataSource&gt;`元素**: - ...

    Mybatis配置.docx

    2. **添加配置文件**:MyBatis的主要配置文件是`mybatis-config.xml`,它定义了MyBatis的整体行为,包括数据源、事务管理器、插件等。配置文件应放在项目资源的根目录下,以便MyBatis能够正确加载。 ```xml &lt;?xml...

    mybatis基础配置

    在这里,我们设置了默认环境为“development”,使用JDBC事务管理器,并配置了一个连接池数据源。 2. **映射器配置(Mappers)**:映射器是MyBatis的核心组件,用于将SQL语句与Java接口绑定。有两种方式来配置映射...

    mybatis基本配置

    其中,你需要指定数据源(dataSource)、事务管理器(transactionManager)以及SqlSessionFactory的配置。例如: ```xml &lt;environment id="development"&gt; &lt;/environment&gt; ... ``` 2. *...

    MyBatis的配置文件

    - `&lt;dataSource&gt;`:数据源,定义如何获取数据库连接,例如使用POOLED(连接池)或UNPOOLED(非连接池)。 3. **映射文件** - `&lt;mappers&gt;`:该元素用于指定映射文件的位置,这些文件包含了SQL语句和结果映射。 - ...

    【MyBatis学习笔记二】——MyBatis配置说明.zip

    这个文件包含了MyBatis的基本设置,如数据源、事务管理器、环境配置等。在配置文件中,我们首先要定义一个`environments`元素,其中包含默认的数据库环境配置。例如: ```xml &lt;environment id="development"&gt; ...

    MyBatis 官方笔记 + MyBatis 3.5.10 官方英文文档

    - **环境(Environment)**:定义了 MyBatis 运行时的环境,包括数据源和事务管理器。 2. **Mapper 映射文件** - **Mapper XML 文件**:包含 SQL 语句和映射规则,每个 Mapper 文件对应一个 Java 接口。 - **@...

    Mybatis最新版-中文手册.pdf

    这时可以使用MyBatis提供的配置类来配置数据源、事务工厂以及其他配置项。例如: ```java DataSource dataSource = BlogDataSourceFactory.getBlogDataSource(); TransactionFactory transactionFactory = new ...

    mybatis 全xml配置

    接下来,配置MyBatis的主配置文件`mybatis-config.xml`,包括数据源、事务管理器以及SqlSessionFactory的配置: ```xml &lt;?xml version="1.0" encoding="UTF-8" ?&gt; &lt;!DOCTYPE configuration PUBLIC "-//mybatis.org...

    mybatis数据库连接

    `&lt;environments&gt;`元素用于定义多个环境配置,例如开发环境、测试环境、生产环境等。每个环境都可以指定不同的数据库连接信息、事务管理器等。`default`属性指定了当前环境的默认值。 environment元素 `...

    myBatis和ibatis的区别

    - **myBatis的数据源配置**更为复杂和灵活,支持多种类型的事务管理器和数据源,并允许配置多个环境,如: ```xml &lt;environment id="development"&gt; ${driver}"/&gt; &lt;/environment&gt; ``` 这种配置方式...

Global site tag (gtag.js) - Google Analytics