Java多数据库访问与事务管理!
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在现代企业级应用中,系统的复杂度不断增加,数据源的多样性和分布式架构的需求也变得愈发重要。Java作为一种广泛应用于后端开发的编程语言,提供了多种方式来处理多数据源访问与事务管理。尤其是在企业级应用中,多个数据库和分布式事务的管理变得至关重要。如何高效地配置多个数据源,如何管理数据库事务,尤其是分布式事务,是每个开发者在构建高可用和高并发系统时必须掌握的技术。
本文将介绍如何在Java应用中实现多数据库访问,讲解Spring Data JPA和MyBatis的多数据源配置方法,并深入探讨事务管理的两种模式:声明式事务和编程式事务,最后将重点介绍分布式事务的管理,涵盖XA协议和TCC(Try-Confirm-Cancel)模式。
一、多数据源配置:Spring Data JPA与MyBatis
1.1 多数据源配置的背景
在一个企业级应用中,可能需要访问多个数据库,比如主数据库和多个子数据库(例如不同地区或部门的数据库),或同一数据的不同存储方式(例如关系型数据库与NoSQL数据库)。为了能够灵活处理多数据源访问,Java提供了不同的框架和工具来配置和管理多个数据源。
1.2 Spring Data JPA多数据源配置
Spring Data JPA是一个方便的框架,用于与关系型数据库进行交互,特别是在基于JPA(Java Persistence API)规范的数据库操作中。Spring Data JPA通过简化JPA实现(如Hibernate)来使得数据访问更容易。为了解决多数据源访问的问题,Spring提供了配置多个DataSource
并通过@Primary
注解选择主数据源的方法。
配置多个数据源
- 配置
DataSource
:在Spring配置中为每个数据源创建DataSource
,分别指定数据库连接参数。 - 配置
EntityManagerFactory
:每个数据源都需要一个EntityManagerFactory
来创建EntityManager
,以便与JPA进行交互。 - 配置
TransactionManager
:每个数据源需要一个PlatformTransactionManager
来管理事务。
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource()) // 使用主数据源
.packages("com.example.model")
.persistenceUnit("primary")
.build();
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
在这个例子中,我们配置了两个数据源:primaryDataSource
和secondaryDataSource
,并通过@Primary
标注primaryDataSource
为默认数据源。然后为每个数据源配置了EntityManagerFactory
和TransactionManager
,以便分别处理不同数据源的事务。
1.3 MyBatis多数据源配置
MyBatis是另一个常用的数据库访问框架,它为SQL语句提供了灵活的映射,允许开发者直接书写SQL语句进行数据操作。与Spring Data JPA类似,MyBatis也支持多数据源的配置。
配置多个数据源
- 配置
DataSource
:与Spring Data JPA相似,首先为每个数据源配置DataSource
。 - 配置
SqlSessionFactory
:每个数据源需要独立的SqlSessionFactory
,用于执行SQL查询和映射。 - 配置
TransactionManager
:与Spring一样,事务管理对于每个数据源来说都是独立的。
@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class MyBatisConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
// 配置第二个数据源
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
在上述代码中,我们配置了两个数据源(primaryDataSource
和secondaryDataSource
),为每个数据源创建了独立的SqlSessionFactory
和TransactionManager
。@MapperScan
注解用于扫描指定的MyBatis Mapper接口。
二、事务管理:声明式事务与编程式事务
在Java中,事务管理是非常关键的一部分。事务可以保证数据一致性,防止在并发环境中发生数据冲突或不一致的情况。Java通过Spring框架提供了两种常见的事务管理模式:声明式事务和编程式事务。
2.1 声明式事务
声明式事务是指通过配置和注解来声明事务管理,而无需显式地在代码中编写事务处理逻辑。Spring提供了非常方便的声明式事务支持,可以通过@Transactional
注解来实现。
示例:声明式事务
@Service
public class UserService {
@Transactional
public void transferMoney(String fromAccount, String toAccount, double amount) {
// 执行数据库操作,转账逻辑
accountDao.debit(fromAccount, amount);
accountDao.credit(toAccount, amount);
}
}
在这个例子中,@Transactional
注解表示transferMoney
方法需要在事务环境中执行。如果方法执行过程中发生异常,Spring会自动回滚事务,确保数据库的一致性。声明式事务的优势是简洁,不需要在代码中显式编写事务处理逻辑。
事务传播行为
Spring提供了多种事务传播行为,例如:
REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则新建一个事务。REQUIRES_NEW
:每次方法调用时都会新建一个事务。NESTED
:如果当前有事务,则在当前事务中嵌套一个子事务。
2.2 编程式事务
编程式事务需要开发者在代码中显式地编写事务管理逻辑。在这种方式中,开发者通过PlatformTransactionManager
来手动管理事务的开始、提交和回滚。
示例:编程式事务
@Service
public class UserService {
@Autowired
private PlatformTransactionManager transactionManager;
public void transferMoney(String fromAccount, String toAccount, double amount) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 执行数据库操作
accountDao.debit(fromAccount, amount);
accountDao.credit(toAccount, amount);
transactionManager.commit(status); // 提交事务
} catch (Exception e) {
transactionManager.rollback(status); // 回滚事务
throw new RuntimeException("Transaction failed", e);
}
}
}
在这个例子中,我们手动创建了一个事务定义(DefaultTransactionDefinition
),设置了事务的隔离级别和传播行为。通过transactionManager.getTransaction(def)
开启事务,通过transactionManager.commit(status)
提交事务,发生异常时通过transactionManager.rollback(status)
回滚事务。
三、分布式事务:XA协议与TCC
在现代分布式系统中,事务往往跨越多个数据库或微服务,因此如何保证跨系统的一致性成为一个关键问题。常见的分布式事务解决方案有XA协议和TCC(Try-Confirm-Cancel)模式。
3.1 XA协议
XA协议是一种两阶段提交协议(2PC),广泛用于分布式事务处理中。XA协议要求每个参与者(数据库)在事务开始时准备提交,并在事务结束时根据协调者的命令执行提交或回滚。
XA协议的基本流程
- 准备阶段:协调者向参与者发出“准备提交”的请求,参与者执行事务操作并进行准备。
- 提交阶段:如果所有参与者都准备好,则协调者发出“提交”命令,所有参与者执行提交操作;如果任何一个参与者准备失败,则发出“回滚”命令,所有参与者回滚事务。
XA协议的优点是简单,易于实现,但它会影响系统的性能和可用性,因为所有参与者必须等待协调者的指令。
3.2 TCC(Try-Confirm-Cancel)
TCC是一种基于补偿机制的分布式事务模型,适用于高并发的场景。TCC将分布式事务分为三个阶段:Try(尝试阶段)、Confirm(确认阶段)和Cancel(取消阶段)。在TCC模式下,每个服务都提供三种操作:
- Try:预留资源并进行必要的检查(类似于预备提交)。
- Confirm:在所有参与者都成功完成Try阶段后,确认操作并提交事务。
- Cancel:如果有任何服务失败,则回滚前面成功的操作。
TCC的优点是高性能和更灵活的补偿机制,但实现起来比XA协议更复杂。
3.3 分布式事务管理框架
- Atomikos:一个支持XA事务的分布式事务管理框架,适用于传统的两阶段提交协议。
- Seata:一个分布式事务框架,支持TCC、AT、Saga等模式,特别适用于微服务架构。
- Narayana:Red Hat提供的一个分布式事务管理框架,支持XA和TCC等协议。
四、总结
在现代Java开发中,多数据源访问和事务管理是构建高性能、可扩展应用的重要技术。Java 通过Spring和MyBatis等框架提供了方便的多数据源配置和事务管理支持,使得开发者能够轻松管理复杂的数据库访问和事务。尤其在分布式系统中,正确选择和实现分布式事务协议(如XA协议或TCC)对于确保系统的一致性和稳定性至关重要。
通过掌握多数据源配置、声明式事务与编程式事务的实现,以及分布式事务的管理策略,开发者能够构建出更加健壮、灵活和高效的系统,为现代企业级应用打下坚实的基础。
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!
- 点赞
- 收藏
- 关注作者
评论(0)