MyBatis配置多数据库

本文详细介绍了MyBatis如何配置多种环境以应用于不同数据库,包括开发、测试和生产环境,以及如何针对不同数据库使用相同的SQL映射。通过配置环境,用户可以灵活地连接MySQL、SQL Server和Oracle等数据库,实现数据库间的无缝切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis 可以配置多种环境。这会帮助你将 SQL 映射应用于多种数据库之中。例如,你也许为开发要设置不同的配置,测试和生产环境。或者你可能有多种生产级数据库却共享相同的模式,所以你会想对不同数据库使用相同的 SQL 映射。这种用例是很多的。一个很重要的问题要记得:你可以配置多种环境,但你只能为每个 SqlSessionFactory实例选择一个。所以,如果你想连接两个数据库,你需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,你就需要三个实例,以此类推。记忆起来很简单: 每个数据库对应一个 SqlSessionFactory,为了明确创建哪种环境,你可以将它作为可选的参数传递给 SqlSessionFactoryBuilder。
可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory  factory  =  sqlSessionFactoryBuilder.build(reader, environment,properties);
如果环境被忽略,那么默认环境将会被加载,如下进行:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);
环境元素定义了如何配置环境。
<environments default="development">
 <environment id="development">
  <transactionManager type="JDBC">
   <property name="..." value="..."/>
  </transactionManager>
  <dataSource type="POOLED">
   <property name="driver" value="${driver}"/>
   <property name="url" value="${url}"/>
   <property name="username" value="${username}"/>
   <property name="password" value="${password}"/>
  </dataSource>
 </environment>
</environments>


注意这里的键:
        1   默认的环境 ID(比如:default=”development”)。
2  每个 environment 元素定义的环境 ID(比如:id=”development”)。
覆盖配置类除了用插件来修改 MyBatis 核心行为之外,你也可以完全覆盖配置类。简单扩展它,然后覆盖其中的任意方法,之后传递它sqlSessionFactoryBuilder.build(myConfig) 方法的调用。这可能会严重影响 MyBatis 的行为,所以要小心。 
3  事务管理器的配置(比如:type=”JDBC”)。

4  数据源的配置(比如:type=”POOLED”)。

默认的环境和环境 ID 是自我解释的。你可以使用你喜欢的名称来命名,只要确定默认的要匹配其中之一


测试时我使用了MySql,Sqlserver,Oracle三个数据库,以MySql为默认数据库,如下:

mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://127.0.0.1:3306/company
mysql.username=root
mysql.password=xiaohu

sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
sqlserver.url=jdbc:sqlserver://127.0.0.1:1434;database=company
sqlserver.username=sa
sqlserver.password=xiaohu

oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
oracle.username=scott
oracle.password=xiaohu

主配置文件:mybatis/mybatis-config.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="jdbc.properties"/>
	
	<!-- 配置类别名 -->
	<typeAliases>
		<typeAlias alias="Emp" type="com.tenghu.mybatis.model.Emp"/>
		<typeAlias alias="Dept" type="com.tenghu.mybatis.model.Dept"/>
	</typeAliases>
	
	<environments default="development">
		<!-- 默认MySq -->
		<environment id="development">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${mysql.driver}"/>
				<property name="url" value="${mysql.url}"/>
				<property name="username" value="${mysql.username}"/>
				<property name="password" value="${mysql.password}"/>
			</dataSource>
		</environment>
		
		<!-- Sqlserver数据库 -->
		<environment id="sqlserver">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${sqlserver.driver}"/>
				<property name="url" value="${sqlserver.url}"/>
				<property name="username" value="${sqlserver.username}"/>
				<property name="password" value="${sqlserver.password}"/>
			</dataSource>
		</environment>
		
		<!-- Oracle -->
		<environment id="oracle">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${oracle.driver}"/>
				<property name="url" value="${oracle.url}"/>
				<property name="username" value="${oracle.username}"/>
				<property name="password" value="${oracle.password}"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 配置映射文件 -->
	<mappers>
		<mapper resource="com/tenghu/mybatis/mapper/DeptMapper.xml"/>
		<mapper resource="com/tenghu/mybatis/mapper/EmpMapper.xml"/>
	</mappers>
</configuration>

打开SqlSession工具类MyBatiUtil.java:

package com.tenghu.mybatis.util;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisUtil {
	private MyBatisUtil(){}
	
	//Mysql Session工厂
	private static SqlSessionFactory mysqlSessionFactory;
	//Sqlserver Session工厂
	private static SqlSessionFactory sqlserverSessionFactory;
	//Oracle Session工厂
	private static SqlSessionFactory oracleSessionFactory;
	
	static{
		try {
			//实例化Mysql Session工厂
			mysqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis/mybatis-config.xml"));
			//实例化SqlServer Session 工厂
			sqlserverSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis/mybatis-config.xml"), "sqlserver");
			//实例化Oracle Session工厂
			oracleSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis/mybatis-config.xml"), "oracle");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 打开MySql会话
	 * @return
	 */
	public static SqlSession openMySqlSession(){
		return mysqlSessionFactory.openSession();
	}
	
	/**
	 * 打开SqlServer会话
	 * @return
	 */
	public static SqlSession openSqlserverSession(){
		return sqlserverSessionFactory.openSession();
	}
	
	/**
	 * 打开Oracle会话
	 * @return
	 */
	public static SqlSession openOracleSession(){
		return oracleSessionFactory.openSession();
	}
	
	/**
	 * 关闭会话
	 * @param sqlSession
	 */
	public static void closeSession(SqlSession sqlSession){
		if(null!=sqlSession)
			sqlSession.close();
	}
}

实体类:

package com.tenghu.mybatis.model;

public class Dept {
	private int deptno;
	private String dname;
	private String loc;	
}
package com.tenghu.mybatis.model;

public class Emp {
	private int id;
	private int age;
	private String name;
}
省略get和set方法

映射文件:EmpMapper.xml和DeptMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tenghu.mybatis.mapper.EmpMapper">
	<select id="queryForList" resultType="Emp">
		select * from emp
	</select>
</mapper>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tenghu.mybatis.mapper.DeptMapper">
	<select id="queryForList" resultType="Dept">
		select * from dept
	</select>
</mapper>

测试类:

package com.tenghu.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.tenghu.mybatis.model.Dept;
import com.tenghu.mybatis.model.Emp;
import com.tenghu.mybatis.util.MyBatisUtil;

public class EmpMapperTest {
	/**
	 * 测试MySql数据库
	 */
	@Test
	public void testMysqlQueryForList(){
		SqlSession sqlSession=null;
		try {
			//获取sql会话
			sqlSession=MyBatisUtil.openMySqlSession();
			//获取集合
			List<Emp> empList=sqlSession.selectList("com.tenghu.mybatis.mapper.EmpMapper.queryForList");
			for (Emp emp : empList) {
				System.out.println(emp.getAge()+"\t"+emp.getId()+"\t"+emp.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//关闭SqlSession
			MyBatisUtil.closeSession(sqlSession);
		}
	}
	/**
	 * 测试Sqlserver数据库
	 */
	@Test
	public void testSqlServerQueryForList(){
		SqlSession sqlSession=null;
		try {
			//获取sql会话
			sqlSession=MyBatisUtil.openSqlserverSession();
			//获取集合
			List<Emp> empList=sqlSession.selectList("com.tenghu.mybatis.mapper.EmpMapper.queryForList");
			for (Emp emp : empList) {
				System.out.println(emp.getAge()+"\t"+emp.getId()+"\t"+emp.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//关闭SqlSession
			MyBatisUtil.closeSession(sqlSession);
		}
	}
	/**
	 * 测试Oracle数据库
	 */
	@Test
	public void testOracleQueryForList(){
		SqlSession sqlSession=null;
		try {
			//获取Sql会话
			sqlSession=MyBatisUtil.openOracleSession();
			List<Dept> deptList=sqlSession.selectList("com.tenghu.mybatis.mapper.DeptMapper.queryForList");
			for (Dept dept : deptList) {
				System.out.println(dept.getDeptno()+"\t"+dept.getDname()+"\t"+dept.getLoc());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//关闭SqlSession
			MyBatisUtil.closeSession(sqlSession);
		}
	}
}

这样就完成了同时连接多个数据库了



<think>嗯,用户问MyBatis是否可以连接多个数据库。我需要先确认MyBatis的功能是否支持这一点。记得MyBatis是一个持久层框架,主要作用是封装数据库操作,简化JDBC的使用。 首先,连接多个数据库的场景,可能需要配置多个数据源。在传统的单一数据源情况下,通常是在MyBatis配置文件中配置一个DataSource,比如使用连接池。但多个数据库的话,就需要多个不同的DataSource实例。 然后想到Spring框架,因为很多项目会用Spring整合MyBatis。在Spring中,可以通过配置多个DataSource,然后为每个数据库创建对应的SqlSessionFactory和Mapper接口。这样不同的Mapper可以使用不同的数据源,从而访问不同的数据库。 不过用户可能没有用Spring,所以需要考虑纯MyBatis的情况。MyBatis本身是否支持多数据源?我记得MyBatis的SqlSessionFactoryBuilder可以根据不同的配置文件创建不同的SqlSessionFactory,每个Factory对应一个数据库。这样在代码中通过不同的Factory打开SqlSession,就能操作不同的数据库。但这样需要在代码中手动管理多个Factory和Session,可能比较麻烦,不如用Spring方便。 另外,动态切换数据源可能也是一个需求。比如根据请求的不同切换到不同的数据库。这时候可能需要自定义数据源路由,通过AOP或者拦截器在运行时决定使用哪个数据源。Spring提供了AbstractRoutingDataSource,可以用来实现动态路由。结合MyBatis的话,可能需要配置这个路由数据源,并在需要的地方切换上下文。 还要考虑事务管理的问题。如果多个数据库操作需要跨库事务,那可能需要分布式事务管理器,比如JTA。不过大多数情况下,可能只是分开操作不同的库,不需要跨库事务。 总结起来,MyBatis本身不直接管理多数据源,但通过结合Spring或者手动配置多个SqlSessionFactory,可以实现连接多个数据库。关键点在于数据源的配置和管理,以及如何在不同情况下使用正确的数据源。 用户可能需要具体的实现步骤,比如配置多个数据源、创建对应的Bean、如何编写Mapper接口等。需要分点说明,结构清晰。同时提醒可能的注意事项,比如事务处理、资源管理,以及性能方面的考虑,比如连接池配置。</think>MyBatis **可以连接多个数据库**,但需要合理配置数据源并管理不同数据库的交互。以下是具体实现方法和关键点: --- ### 一、实现多数据库连接的方案 #### 方案1:基于Spring框架的多数据源配置(推荐) 如果项目整合了Spring/Spring Boot,可通过以下步骤实现: 1. **定义多个数据源** 在`application.yml`中配置多个数据库连接信息: ```yaml spring: datasource: db1: url: jdbc:mysql://localhost:3306/db1 username: root password: 123456 db2: url: jdbc:oracle:thin:@localhost:1521:db2 username: admin password: admin123 ``` 2. **创建数据源Bean** 使用`@Configuration`定义多个`DataSource`: ```java @Configuration public class DataSourceConfig { @Bean(name = "db1DataSource") @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource db1DataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "db2DataSource") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource db2DataSource() { return DataSourceBuilder.create().build(); } } ``` 3. **配置多个SqlSessionFactory** 为每个数据源创建独立的`SqlSessionFactory`: ```java @Bean(name = "db1SqlSessionFactory") public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/db1/*.xml")); return bean.getObject(); } ``` 4. **指定Mapper接口绑定的数据源** 通过`@MapperScan`注解指定不同包路径: ```java @Configuration @MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory") public class Db1MyBatisConfig {} @Configuration @MapperScan(basePackages = "com.example.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory") public class Db2MyBatisConfig {} ``` --- #### 方案2:纯MyBatis手动管理(无Spring) 直接通过代码动态切换`SqlSession`: ```java // 加载不同数据库配置 InputStream inputStream1 = Resources.getResourceAsStream("mybatis-db1-config.xml"); SqlSessionFactory sqlSessionFactory1 = new SqlSessionFactoryBuilder().build(inputStream1); InputStream inputStream2 = Resources.getResourceAsStream("mybatis-db2-config.xml"); SqlSessionFactory sqlSessionFactory2 = new SqlSessionFactoryBuilder().build(inputStream2); // 使用时选择对应的SqlSession try (SqlSession session1 = sqlSessionFactory1.openSession()) { UserMapper userMapper = session1.getMapper(UserMapper.class); userMapper.selectUser(1); } try (SqlSession session2 = sqlSessionFactory2.openSession()) { OrderMapper orderMapper = session2.getMapper(OrderMapper.class); orderMapper.selectOrder(100); } ``` --- ### 二、注意事项 1. **事务管理** 跨数据库操作时,默认事务管理器(如`DataSourceTransactionManager`)无法保证分布式事务一致性。如需强一致性,需引入JTA或Seata等分布式事务解决方案。 2. **动态数据源路由** 可通过继承`AbstractRoutingDataSource`实现动态切换: ```java public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); // 从ThreadLocal获取当前数据源标识 } } ``` 3. **性能优化** - 为每个数据源配置独立的连接池(如HikariCP)。 - 避免频繁切换数据源,尽量在业务层隔离不同数据库操作。 --- ### 三、典型应用场景 - 主从数据库分离(读写分离) - 多租户系统(每个租户独立数据库) - 数据迁移或跨数据库查询 通过合理设计,MyBatis完全能够满足多数据库连接需求,建议优先结合Spring框架简化配置
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小老虎Love

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值