目录
本文将对如何使用Springboot+MyBatis操作多数据源进行简单示例和介绍,项目的完整目录层次如下图所示。
添加依赖与配置
首先,需要在工程POM文件中引入MyBatis和MySQL的Maven依赖。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<!-- 添加 MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
<!-- 添加 MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
其中mybatis-spring-boot-starter是 MyBatis 官方提供的Starter, 其Github 源码地址: https://github.com/mybatis/spring-boot-starter 。
此外,mybatis-spring-boot-stater 的官方文档地址:http://www.mybatis.org/spring-boot-starter/,MyBatis 官方中文文档地址:http://www.mybatis.org/mybatis-3/zh/java-api.html 。
然后,在核心配置文件application.properties中添加数据源相关配置。
#########################################################
### Primary DataSource -- DataSource 1 configuration ###
#########################################################
primary.datasource.url=jdbc:mysql://localhost:3306/dev1?useUnicode=true&characterEncoding=utf8
primary.datasource.driverClassName=com.mysql.jdbc.Driver
primary.datasource.username=root
primary.datasource.password=123456
#########################################################
### Secondary DataSource -- DataSource 2 configuration ##
#########################################################
secondary.datasource.url=jdbc:mysql://localhost:3306/dev2?useUnicode=true&characterEncoding=utf8
secondary.datasource.driverClassName=com.mysql.jdbc.Driver
secondary.datasource.username=root
secondary.datasource.password=123456
配置数据源
首先,分别为每一个数据源各定义一个配置类,在配置类中通过注解@MapperScan来为不同包下的Mapper分别创建不同SqlSessionFactory、SqlSessionTemplate和DataSourceTransactionManager,用来操作不同的数据源。
/**
* 数据源 1 配置类
*/
@Configuration
@MapperScan(basePackages = "com.pengjunlee.primary.mapper", sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "primary.datasource")
@Primary
public DataSource createDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/primary/*.xml"));
return bean.getObject();
}
@Primary
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate primarySqlSessionTemplate(
@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
/**
* 数据源 2 配置类
*/
@Configuration
@MapperScan(basePackages = "com.pengjunlee.secondary.mapper", sqlSessionTemplateRef = "secondarySqlSessionTemplate")
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "secondary.datasource")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/secondary/*.xml"));
return bean.getObject();
}
@Bean(name = "secondaryTransactionManager")
public DataSourceTransactionManager secondaryTransactionManager(
@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondarySqlSessionTemplate")
public SqlSessionTemplate secondarySqlSessionTemplate(
@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
定义Mapper
由于注解@MapperScan是通过包名来区分哪些Mapper用来操作哪个数据源,故而需要将不同数据源的Mapper接口类定义在不同的包中。
此处为了示例,定义了User(用户)和Department(部门)两个实体类,分别对应数据源一和数据源二。
/**
* 用户
*/
public class User {
private Long id;
private String name;
private Integer age;
// 此处省略get和set方法
}
/**
* 部门
*/
public class Department {
private Long id;
private String name;
// 此处省略get和set方法
}
package com.pengjunlee.primary.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.pengjunlee.bean.User;
/**
* 数据源 1 Mapper
*/
@Mapper
public interface UserMapper {
User selectById(@Param("id") Long id);
void deleteById(@Param("id") Long id);
}
package com.pengjunlee.secondary.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.pengjunlee.bean.Department;
/**
* 数据源 2 Mapper
*/
@Mapper
public interface DepartmentMapper {
Department selectById(@Param("id") Long id);
void deleteById(@Param("id") Long id);
}
注意:在定义Mapper接口的时候,其所在包一定要与配置文件中指定的包路径一致。
使用Mapper
在实际项目中我们一般都会将定义好的Mapper自动装配到Service层进行调用,此时要格外注意事务。
以使用UserMapper为例,UserService接口定义如下。
public interface UserService {
// 根据主键查询用户
User getUserById(Long id);
// 根据主键删除用户
void deleteUserById(Long id);
}
在接口实现类UserServiceImpl中自动装配UserMapper来完成对数据源1的操作。
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(Long id) {
return userMapper.selectById(id);
}
@Override
@Transactional("primaryTransactionManager")// 注意事务
public void deleteUserById(Long id) {
userMapper.deleteById(id);
throw new RuntimeException();
}
}
启动类测试
在启动类中进行测试,测试代码如下。
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
UserMapper userMapper = context.getBean(UserMapper.class);
User user = userMapper.selectById(3L);
System.out.println(user.getName());
DepartmentMapper deptMapper = context.getBean(DepartmentMapper.class);
Department dept = deptMapper.selectById(2L);
System.out.println(dept.getName());
// 通过删除操作测试事务
// DepartmentService deptService =
// context.getBean(DepartmentService.class);
// deptService.deleteDepartmentById(2L);
UserService userService = context.getBean(UserService.class);
userService.deleteUserById(3L);
}
}
启动程序,各数据源中的数据都能查询成功且支持事务。
本文项目源码已上传至CSDN,资源地址:https://download.csdn.net/download/pengjunlee/10612419