鲁春利的工作笔记,好记性不如烂笔头
用 @Transactional 注解声明式地管理事务
Spring 还允许简单地用 @Transactional 注解来标注事务方法(只能标注公有方法)。
在 Bean 配置文件中增加 <tx:annotation-driven> 元素声明, 并为之指定事务管理器。如果事务处理器的名称是 transactionManager, 在<tx:annotation-driven> 元素中可以省略 transaction-manager 属性,元素会自动检测该名称的事务处理器。
Spring配置文件(spring-context-tx-program.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/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 配置Spring进行组件扫描的路径 base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类,当需要扫描多个包时, 可以使用逗号分隔; resource-pattern 如果仅希望扫描特定的类而非基包下的所有类,如 resource-pattern="dao/*.class"; <context:include-filter> 子节点表示要包含的目标类; <context:exclude-filter> 子节点表示要排除在外的目标类; <context:component-scan> 下可以拥有若干个 <context:include-filter> 和 <context:exclude-filter> 子节点; 如:扫描符合@Service @Repository的类 <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> --> <context:component-scan base-package="com.invicme.apps.tx.annotation" /> <!-- 加载配置属性文件 --> <context:property-placeholder ignore-unresolvable="true" location="classpath:spring/jdbc.properties" /> <!-- 数据源配置, 使用 BoneCP 数据库连接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 略 --> </bean> <!-- 配置 Spirng 的 JdbcTemplate --> <bean id="jdbcTemplate" 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:annotation-driven transaction-manager="transactionManager" /> </beans>
业务层实现
package com.invicme.apps.tx.annotation.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.invicme.apps.tx.annotation.dao.BookShopDao; /** * * @author lucl * */ @Service("bookShopService") public class BookShopServiceImpl implements BookShopService { @Autowired private BookShopDao bookShopDao; /** * 事务注解 * 1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时如何使用事务, * 默认取值为 REQUIRED, 即使用调用方法的事务; * REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起. * 2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED; * 3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的属性进行设置. 通常情况下去默认值即可. * 4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据, 可以帮助数据库引擎优化事务. * 5.使用 timeout 指定强制回滚之前事务可以占用的时间. */ @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=false, timeout=3) @Override public void purchase(String ano, String isbn) { //1. 获取书的单价 int price = bookShopDao.findBookPriceByIsbn(isbn); //2. 更新数的库存 bookShopDao.updateBookStock(isbn); //3. 更新用户余额(抛出异常,第二步的操作也不会成功) bookShopDao.updateUserAccount(ano, price); } }
单元测试类
public class TestAnnotationTransaction { @Test public void testAnnotationTransaction(){ ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-context-tx-annotation.xml"); BookShopService bookShopService = ctx.getBean(BookShopService.class); bookShopService.purchase("zhangsan", "8888"); } }
用事务通知声明式地管理事务
时间: 2024-10-22 11:31:42