一、概述
声明式事务(declarative transaction management)是Spring提供的对程序事务管理的一种方式,Spring的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,是指在配置文件中声明,用在Spring配置文件中声明式的处理事务来代替业务逻辑中使用代码处理事务,这样做的好处是:事务管理不侵入开发的组件,具体来说就是业务逻辑对象不会意识到自己正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策略的话,也只需要在配置文件中修改配置即可,在不需要事务管理的时候,修改一下配置信息,即可移除事务管理服务,无需改变代码重新编译,这样维护起来也很方便,Spring中是使用aop来完成声明式事务管理的,因而声明式事务是以方法为单位的,也即声明式事务是作用在业务方法上的。
二、声明式事务(xml方式)环境搭建
2.1、项目概览
2.2、配置思路
第一步:配置事务管理器;
第二步:配置事务要处理的方法;注意事项:一旦配置了事务方法名称规则后,service中的方法一定要按照这里配置的名称,否则事务配置不生效;
第三步:配置aop;
2.3、pom.xml
同 系列四 pom.xml
2.4、applicationContext.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="org.star"/>
<!-- 数据源 -->
<context:property-placeholder location="db.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<!--
配置sqlSessionFactory:读取配置文件,获取数据库相关的信息
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="org.star.entity.model"></property>
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"></property>
</bean>
</property>
<!-- 分页插件 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--
reasonable=true解释:如果用户输入的不合理的pageSize参数,pageHelper会自动进行调整
-->
<value>
helperDialect=mysql
reasonable=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--
配置mapper接口的位置,并指定sqlSessionFactory
sqlSession = sqlSessionFactory.openSession();
mapper = sqlSession.getMapper();
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.star.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--
声明式事务配置:
spring中的事务是基于aop实现,但使用的不是通知而是拦截器
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定义事务的对象信息 -->
<tx:attributes>
<!-- transfer*:表示以transfer开头的所有方法 -->
<tx:method name="transfer*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- aop配置 -->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* org.star.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
</aop:config>
</beans>
2.5、db.properties
同 系列四 db.properties
2.6、AccountDO.java
同 系列四 AccountDO.java
2.7、AccountMapper.java
同 系列四 AccountMapper.java
2.8、AccountMapper.xml
同 系列四 AccountMapper.xml
2.9、AccountService.java
同 系列四 AccountService.java
2.10、AccountServiceImpl.java
java
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/24 8:25
* @Description:
*/
@Service
public class AccountServiceImpl implements AccountService {
@Resource
private AccountMapper accountMapper;
/**
* 转账
*
* @return
*/
@Override
public void transferMoney() {
try {
// Jack 转出100元
accountMapper.accountExpenditure("Jack", 100);
// 模拟异常
int i = 10 /0;
// Rose 入账100元
accountMapper.accountEntry("Rose", 100);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
2.11、SpringJunitTest.java
同 系列四 SpringJunitTest.java