MyBatis 多数据源切换
你是一个java开发高手,现在要给一个0基础的小白讲清楚:在 使用mybatis的时候,代码层面 是在哪里 调用的 datasource ,如何创建的 sqlsession,如果遇到多数据源 如何在调用mapper时 手动切换 数据源连接信息。
1. 在使用 MyBatis 时,代码层面在哪里调用的 DataSource
1.1 理解 DataSource 的作用
DataSource 是 Java 中用于获取数据库连接的接口,MyBatis 使用它来管理数据库连接。在 MyBatis 里,DataSource 负责提供数据库连接,以便执行 SQL 语句。1.2 代码层面调用 DataSource 的位置
在 MyBatis 中,
DataSource 通常在配置 SqlSessionFactory 时被使用。SqlSessionFactory 是 MyBatis 的核心组件,用于创建 SqlSession 对象,而 SqlSession 则用于执行 SQL 操作。以下是一个简单的示例:java
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import java.sql.SQLException;
public class MyBatisExample {
public static void main(String[] args) throws SQLException {
// 创建 DataSource
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("password");
// 创建事务工厂
TransactionFactory transactionFactory = new JdbcTransactionFactory();
// 创建环境
Environment environment = new Environment("development", transactionFactory, dataSource);
// 创建配置对象
Configuration configuration = new Configuration(environment);
// 这里可以添加映射器类
// configuration.addMapper(UserMapper.class);
// 创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
// 使用 SqlSessionFactory 创建 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
// 这里可以执行 SQL 操作
}
}
}
在上述代码中,
PooledDataSource 是 MyBatis 提供的一个连接池实现,我们在创建 SqlSessionFactory 之前先创建了 DataSource,并将其传递给 Environment 对象,最终传递给 Configuration 对象,这样 SqlSessionFactory 就知道从哪里获取数据库连接了。2. 如何创建 SqlSession
2.1 通过 SqlSessionFactory 创建 SqlSession
SqlSession 是 MyBatis 执行 SQL 操作的核心对象,它提供了执行 SQL 语句、管理事务等功能。创建 SqlSession 的步骤如下:- 创建
DataSource。 - 创建
TransactionFactory。 - 创建
Environment。 - 创建
Configuration。 - 使用
SqlSessionFactoryBuilder构建SqlSessionFactory。 - 使用
SqlSessionFactory创建SqlSession。
以下是示例代码:
java
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import java.sql.SQLException;
public class CreateSqlSessionExample {
public static void main(String[] args) throws SQLException {
// 创建 DataSource
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("password");
// 创建事务工厂
TransactionFactory transactionFactory = new JdbcTransactionFactory();
// 创建环境
Environment environment = new Environment("development", transactionFactory, dataSource);
// 创建配置对象
Configuration configuration = new Configuration(environment);
// 这里可以添加映射器类
// configuration.addMapper(UserMapper.class);
// 创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
// 使用 SqlSessionFactory 创建 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
// 这里可以执行 SQL 操作
System.out.println("SqlSession 创建成功");
}
}
}
3. 遇到多数据源时,如何在调用 Mapper 时手动切换数据源连接信息
3.1 实现思路
为了实现多数据源的手动切换,我们可以使用
ThreadLocal 来存储当前线程使用的数据源信息,然后通过 AOP 或者拦截器在执行 SQL 操作之前切换数据源。3.2 示例代码
以下是一个简单的多数据源切换示例:
1. 创建数据源上下文类
java
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
2. 创建动态数据源类
java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(Map<Object, Object> targetDataSources, Object defaultTargetDataSource) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
3. 配置数据源
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource1() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/db1");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public DataSource dataSource2() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/db2");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public DataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("dataSource1", dataSource1());
targetDataSources.put("dataSource2", dataSource2());
return new DynamicDataSource(targetDataSources, dataSource1());
}
}
4. 在调用 Mapper 时手动切换数据源
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void doSomethingWithDataSource1() {
DataSourceContextHolder.setDataSource("dataSource1");
try {
// 执行 Mapper 方法
userMapper.selectAllUsers();
} finally {
DataSourceContextHolder.clearDataSource();
}
}
public void doSomethingWithDataSource2() {
DataSourceContextHolder.setDataSource("dataSource2");
try {
// 执行 Mapper 方法
userMapper.selectAllUsers();
} finally {
DataSourceContextHolder.clearDataSource();
}
}
}
在上述代码中,我们通过
DataSourceContextHolder 来存储当前线程使用的数据源信息,DynamicDataSource 会根据 DataSourceContextHolder 中存储的信息来切换数据源。在调用 Mapper 方法之前,我们可以手动设置要使用的数据源,执行完后清除数据源信息。这样,我们就实现了在调用 Mapper 时手动切换数据源连接信息的功能。
摘抄自网络,便于检索查找。

浙公网安备 33010602011771号