mybatis的SqlSessionFactoryBean只在spring配置文件第一次加载的时候初始化,动态切换数据源之后并没有通知SqlSessionFactoryBean修改databaseId为当前数据源,所以依旧使用默认数据源执行sql。这一问题该怎么解决详细说明一下,mybatisplush版本是3.2.0
时间: 2024-03-10 10:44:30 浏览: 128
mybatis+spring实现动态切换数据源
5星 · 资源好评率100%
在 MyBatis 中实现动态切换数据源主要有两种方法:一种是使用多个 SqlSessionFactory 实例,每个实例对应一个数据源;另一种是在一个 SqlSessionFactory 实例中动态切换数据源。下面分别介绍这两种方法的实现。
#### 方法一:使用多个 SqlSessionFactory 实例
在 Spring 配置文件中定义多个 SqlSessionFactory 实例,每个实例对应一个数据源,例如:
```xml
<bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db1"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db2"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource1"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>
<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource2"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>
<bean id="databaseIdProvider" class="org.mybatis.spring.boot.autoconfigure.DatabaseIdProviderAdapter">
<property name="properties">
<value>
MySQL: mysql
</value>
</property>
</bean>
```
然后在代码中根据需要选择对应的 SqlSessionFactory 实例,例如:
```java
@Autowired
@Qualifier("sqlSessionFactory1")
private SqlSessionFactory sqlSessionFactory1;
@Autowired
@Qualifier("sqlSessionFactory2")
private SqlSessionFactory sqlSessionFactory2;
public void doSomething(boolean useDataSource1) {
SqlSessionFactory sqlSessionFactory = useDataSource1 ? sqlSessionFactory1 : sqlSessionFactory2;
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// 使用 sqlSession 执行 SQL
} finally {
sqlSession.close();
}
}
```
#### 方法二:在一个 SqlSessionFactory 实例中动态切换数据源
在 Spring 配置文件中定义一个 SqlSessionFactory 实例,然后在代码中动态切换数据源。具体实现方式如下:
首先在 Spring 配置文件中定义 dataSource 和 SqlSessionFactory 实例:
```xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db1"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>
<bean id="databaseIdProvider" class="org.mybatis.spring.boot.autoconfigure.DatabaseIdProviderAdapter">
<property name="properties">
<value>
MySQL: mysql
</value>
</property>
</bean>
```
然后在代码中使用 ThreadLocal 存储当前数据源的名称,在执行 SQL 之前根据当前数据源名称动态修改 SqlSessionFactory 中的 databaseId 属性,例如:
```java
@Autowired
private SqlSessionFactory sqlSessionFactory;
private static final ThreadLocal<String> dataSourceName = new ThreadLocal<>();
public static void setDataSourceName(String name) {
dataSourceName.set(name);
}
public static void clearDataSourceName() {
dataSourceName.remove();
}
public void doSomething() {
String name = dataSourceName.get();
if (name == null) {
throw new IllegalStateException("Data source name is not set.");
}
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Configuration configuration = sqlSession.getConfiguration();
configuration.setDatabaseId(name);
// 使用 sqlSession 执行 SQL
} finally {
clearDataSourceName();
}
}
```
上述代码中,setDataSourceName() 方法用于设置当前数据源的名称,clearDataSourceName() 方法用于清除当前数据源的名称。在执行 SQL 之前,首先从 ThreadLocal 中获取当前数据源的名称,然后根据名称修改 SqlSessionFactory 中的 databaseId 属性,最后使用 SqlSession 执行 SQL。注意使用完毕后需要清除当前数据源的名称,否则可能会影响后续的 SQL 执行。
阅读全文