一.基于注解
步骤如下:
- 引入jar(mysql驱动,c3p0数据源,spring的必要jar)
- applicationContext.xml的配置
- Service和Dao的类上都加上对应的注解使其在ioc容器中,service的方法上面加上注解@Transactional
applicationContext.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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.transaction.demo"></context:component-scan> <!-- 导入资源文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置 C3P0 数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </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>
编程式事务和声明式事务:
- 编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚. 在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码.
- 声明式事务管理: 大多数情况下比编程式事务管理更好用. 它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理. 事务管理作为一种横切关注点, 可以通过 AOP 方法模块化. Spring 通过 Spring AOP 框架支持声明式事务管理.
事务的传播行为:
利用的场景介绍:
假如用户需要购买一本书号为isbn的书,需要做以下几件事情,这一系列的事情都必须放在一个事务里面,买一本书的事务,我们称之为事务A
(根据isbn检查这本书的库存是否足够,如果不够的话,向外抛出异常,
检查用户余额是否足额,如果不够的话,向外抛出异常,
如果没有异常,则更新库存,从用户的银行卡扣钱)
假如用户在一个订单里面除了买了书a,还买了书c,书d,买这三本书是一个订单也在一个事务里面,我们称之为事务B
假如用户的余额只够买书a,还书b,那么运行结果是什么呢?
前两本成功,后一本失败呢?
三本书的购买均以失败告终?
这个时候,就取决于事务A上被设置的传播属性propagation,
三本书的购买都失败的场合 ⇒ REQUIRED,propagation的默认值也是REQUIRED,则启用调用方法的事务,也就是事务B的事务,挂起自己本身的事务A
前两本成功的场合 ⇒ propagation是REQUIRES_NEW的时候,则将调用方法的事务挂起,也就是事务B的事务被挂起,启用自己本身的事务
@Transactional的其他属性介绍:
-
- 使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED
- 通常情况下spring的声明式事务对多有的运行时异常进行回滚,也可以通过属性(rollbackFor,rollbackForClassName,noRollbackFor,noRollbackForClassName)来进行设置
- 使用readOnly指定事务为只读,这样帮助数据库引擎优化事务
- timeout指定强制回滚之前事务可以占用的时间
二.基于XML文件配置
步骤如下:
- 引入jar(mysql驱动,c3p0数据源,spring的必要jar)
- applicationContext-xml.xml的配置
- Service和Dao的类和方法上所有的注解去掉
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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.transaction.demo.xml"></context:component-scan> <!-- 导入资源文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置 C3P0 数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置 Spirng 的 JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置 dao/service bean (此处的配置省略) --> <!-- 1. 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 2. 配置事务属性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 根据方法名指定事务的属性 --> <tx:method name="purchase" propagation="REQUIRES_NEW"/> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.transaction.demo.xml.tx.service.*.*(..))" id="txPointCut"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> </beans>
时间: 2024-12-12 06:55:19