Spring Data JPA 和mybatis 多数据源
时间: 2025-05-12 17:27:30 浏览: 26
### 如何在项目中同时使用 Spring Data JPA 和 MyBatis 实现多数据源管理
#### 1. 多数据源的概念
在一个应用程序中,如果需要连接多个数据库实例来完成业务逻辑,则称为多数据源配置。这种场景下,可以通过 Spring Boot 提供的灵活性,分别针对不同数据源配置对应的持久化技术(如 JPA 或 MyBatis)。这种方式能够满足复杂项目的多样化需求[^2]。
---
#### 2. 技术选型与特点比较
JPA 是一种基于 ORM 的解决方案,允许开发人员以面向对象的方式操作数据库,简化了 Java 对象和关系型数据库之间的映射过程。而 MyBatis 则提供了更高的 SQL 控制能力,适用于复杂的查询场景。两者的差异在于对象映射方式、移植性和批量处理效率等方面[^4]。
---
#### 3. 配置步骤详解
##### (1)引入依赖
为了支持多数据源管理和两种持久化框架,在 `pom.xml` 文件中需添加以下依赖:
```xml
<dependencies>
<!-- Spring Boot Starter Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MyBatis-Spring-Boot-Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- 数据库驱动 (MySQL为例) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
```
上述代码片段展示了如何引入必要的 Maven 依赖项。
---
##### (2)数据源分离配置
假设存在两个数据源:`dataSourceA` 使用 JPA 进行操作,`dataSourceB` 使用 MyBatis 进行操作。可以在 `application.yml` 中定义如下配置:
```yaml
spring:
datasource:
a:
url: jdbc:mysql://localhost:3306/db_a?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
b:
url: jdbc:mysql://localhost:3306/db_b?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
```
此部分描述了如何通过 YAML 文件区分不同的数据源及其属性。
---
##### (3)自定义配置类
为每个数据源单独创建 Bean 容器并绑定至对应的技术栈。
###### A. 针对 JPA 的数据源配置 (`DataSourceAConfig`)
```java
@Configuration
@EnableTransactionManagement
@PropertySource({"classpath:datasource-a.properties"})
public class DataSourceAConfig {
@Bean(name = "dataSourceA")
@ConfigurationProperties(prefix = "spring.datasource.a")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactoryA")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, @Qualifier("dataSourceA") DataSource dataSource) {
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
return builder.dataSource(dataSource).properties(properties)
.packages("com.example.jpa.entity").persistenceUnit("unitA").build();
}
@Primary
@Bean(name = "transactionManagerA")
public PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactoryA") EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
```
这段代码实现了第一个数据源的具体初始化逻辑,并将其关联到 JPA 持久层[^5]。
---
###### B. 针对 MyBatis 的数据源配置 (`DataSourceBConfig`)
```java
@Configuration
@MapperScan(basePackages = "com.example.mybats.mapper", sqlSessionFactoryRef = "sqlSessionFactoryB")
public class DataSourceBConfig {
@Bean(name = "dataSourceB")
@ConfigurationProperties(prefix = "spring.datasource.b")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactoryB")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSourceB") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
return factoryBean.getObject();
}
@Bean(name = "sqlSessionTemplateB")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryB") SqlSessionFactory sessionFactory) {
return new SqlSessionTemplate(sessionFactory);
}
}
```
该段代码完成了第二个数据源的构建工作,并指定它服务于 MyBatis 映射文件。
---
##### (4)事务管理
由于涉及多个数据源的操作,因此需要特别关注分布式事务的支持情况。可以利用 Spring 的声明式事务机制配合动态代理功能实现跨数据源的一致性控制[^3]。
示例代码展示了一个简单的事务边界设定:
```java
@Service
@Transactional(transactionManager = "transactionManagerA", rollbackFor = Exception.class)
public class CandidateService {
private final CandidateRepository repository;
public CandidateService(CandidateRepository repository) {
this.repository = repository;
}
public void processCandidate(long id) {
try {
// 调用 Repository 方法执行保存或其他操作
repository.findById(id).orElseThrow(() -> new RuntimeException("Not found"));
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
```
此处强调了如何显式指明所使用的事务管理器名称。
---
### 总结
以上内容介绍了如何在同一 Spring Boot 应用程序中整合 JPA 和 MyBatis 并实施多数据源策略的方法。这种方法充分利用了两者的优势,既保留了 JPA 的简洁易用特性,又兼顾了 MyBatis 在复杂查询方面的强大表现力。
---
阅读全文
相关推荐



















