Spring基础使用八
基于注解的声明式事务
Spring提供了@Transactional注解实现事务管理
配置@Transactional
- 配置Spring的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"
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">
<!--扫描组件-->
<context:component-scan base-package="com.wfy"></context:component-scan>
<!-- 导入jdbc.properties-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!-- 创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--
开启事务驱动注解
将使用@Translational注解所标识的方法或类中所有的方法使用事务进行管理
transaction-manager属性设置事务管理器的id
若事务管理器的bean的id默认为transactionManager,则该属性可以默认不写
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
事务管理:
通过tx:annotational-driven元素配置事务注解驱动,tx:annotational-driven元素中有一个常用属性transactional-manager,该属性用于指定事务管理器
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--
开启事务驱动注解
将使用@Translational注解所标识的方法或类中所有的方法使用事务进行管理
transaction-manager属性设置事务管理器的id
若事务管理器的bean的id默认为transactionManager,则该属性可以默认不写
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
- 在service层使用@Transactional注解
package com.wfy.service.impl;
import com.wfy.dao.BookDao;
import com.wfy.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Override
@Transactional
public void buyBook(Integer userId, Integer bookId) {
//查询图书的价格
Integer price= bookDao.getPriceById(bookId);
//更新图书的库存
bookDao.updateBook(bookId);
//更新用户的余额
bookDao.updateBalance(userId,price);
}
}
- 测试案例
package com.wfy.spring.test;
import com.wfy.controller.BookController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx-annotation.xml")
public class TxByAnnotation {
/**声明式事务的配置步骤:
* 1.在Spring的配置文件中配置事务管理器
* 2.开启事务的注解驱动
*在需要被事务管理的方法上,添加@Transactional注解,该方法就会被事务管理
* @Transactional注解标识的位置:
* 1.标识在方法上
* 2.标识在类上,则类中所有的方法都会被事务管理
*/
@Autowired
private BookController bookController;
@Test
public void testByBook(){
bookController.buyBook(1,1);
}
}
只有当声明的事务中的所有方法全部执行,数据才会更新
声明式事务的属性
- 只读
@Transactional(readOnly = true)
如果对增删改操作设置只读,则会报以下错误:
Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
- 超时
@Transactional(timeout = 3 )
超时则会报以下错误:
org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Tue Nov 01 19:20:14 CST 2022
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。此时程序很可能会出现问题,出现问题的程序应该会被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。
超时回滚,释放资源
- 回滚策略
声明式事务默认只针对运行时异常回滚,编译时异常不回滚。
@Transactional(noRollbackFor =ArithmeticException.class )
用于指定不会导致事务回滚的异常类数组
@Transactional(noRollbackForClassName = "java.lang.ArithmeticException")
用于指定不会导致事务回滚的异常类数组名称
@Transactional(RollbackFor)
用于指定导致事务回滚的异常类数组
@Transactional(RollbackForClassName)
用于指定导致事务回滚的异常类数组名称
- 事务隔离级别
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了各种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
@Transactional( isolation = Isolation.DEFAULT)
用于指定事务的隔离级别
- 传播行为
@Transactional(propagation = Propagation.REQUIRED)
默认情况,表示如果当前线程上有已经开启的事务可用,那么就在这个事务中运行。
@Transactional( propagation = Propagation.REQUIRES_NEW)
表示不管当前线程上是否有已经开启的事务,都要开启新事务。
基于XML的声明式事务
配置Spring的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="com.wfy"></context:component-scan>
<!-- 导入jdbc.properties-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!-- 创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务通知-->
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="buyBook"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="tx" pointcut="execution(* com.wfy.service.impl.*.*(..))"></aop:advisor>
</aop:config>
</beans>
配置文件:
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务通知-->
<tx:advice id="tx" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="buyBook"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="tx" pointcut="execution(* com.wfy.service.impl.*.*(..))"></aop:advisor>
</aop:config>
标签:事务,org,Spring,Transactional,基础,回滚,springframework,使用,import From: https://www.cnblogs.com/wfy-studying/p/16849067.html注意:基于xml实现的声明式事务,必须引入aspectJ的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.23</version> </dependency>