Sping中的aop事务
Spring封装了事务管理代码
1.事务操作依旧是:打开事务、提交事务、回滚事务
2.事务的操作对象
(1)因为在不同平台,操作事务的代码各不相同.spring提供了一个接口:
PlatformTransactionManager 接口
-
DataSourceTransactionManager
-
HibernateTransitionmanager
注意:在spring中玩事务管理.最为核心的对象就是TransactionManager对象
(2)spring管理事务的属性介绍
1.事务的隔离级别
-
1 读未提交
-
2 读已提交
-
4 可重复读
-
8 串行化
2.是否只读
- true 只读
- false 可操作
3. 事务的传播行为
- PROPAGATION_REQUIRED:如果当前没事务,就创建一个新事务,如果当前存在事务,就加入该事务,是最常用的设置
- PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,以非事务执行
- PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
Spring管理事务方式
三种方式:编码式、xml配置(aop)、注解配置(aop)
(1)编码式(了解)
以转账为例:
1.将核心事务管理器配置到spring容器
<!-- 事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2.配置TransactionTemplate模板
<!-- 事务模板对象 -->
<bean name="transactionTemplate"class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
3.将事务模板注入Service
<!-- 3.Service -->
<bean name="accountService" class="cn.hncu.service.AccountServiceImpl">
<property name="ad" ref="accountDao"></property>
<property name="tt" ref="transactionTemplate"></property>
</bean>
4.在Service中调用模板
<!-- 3.Service -->
<bean name="accountService" class="cn.hncu.service.AccountServiceImpl">
<property name="ad" ref="accountDao"></property>
<property name="tt" ref="transactionTemplate"></property>
</bean>
(2)xml配置(aop)
1.导包:
2.导入新的约束(tx)
-
beans: 最基本
-
context:读取properties配置
-
aop:配置aop
-
tx:配置事务通知
3.配置通知
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以方法为单位,指定方法应用什么事务属性 isolation:隔离级别 propagation:传播行为 read-only:是否只读 -->
<!-- REPEATABLE_READ 可重复读 READ_COMMITTED 读已提交 READ_UNCOMMITTED 读未提交 SERIALIZABLE
串行化 -->
<tx:method name="aave*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="true" />
<tx:method name="transfer" isolation="REPEATABLE_READ"
propagation="REQUIRED" read-only="false" />
</tx:attributes>
</tx:advice>
4.配置将通知织入目标
<!-- 配置织入 -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))"
id="txPc" />
<!-- 配置切面 : 通知+切点 advice-ref:通知的名称 pointcut-ref:切点的名称 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
(3)注解配置(aop)
1.导包
2.导入新的约束(tx)
3.开启注解管理事务
<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>
4.使用注解
dao:
package cn.hncu.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
@Override
public void increaseMoney(Integer id, Double money) {
getJdbcTemplate().update("update t_account set money =money+? where id=? ", money,id);
}
@Override
public void decreaseMoney(Integer id, Double money) {
getJdbcTemplate().update("update t_account set money =money-? where id=? ", money,id);
}
}
service:
package cn.hncu.service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import cn.hncu.dao.AccountDao;
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class AccountServiceImpl implements AccountService {
private AccountDao ad;
private TransactionTemplate tt;
public AccountDao getAd() {
return ad;
}
public void setAd(AccountDao ad) {
this.ad = ad;
}
public TransactionTemplate getTt() {
return tt;
}
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
/*@Override
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void transfer(final Integer from,final Integer to,final Double money) {
//减钱
ad.decreaseMoney(from, money);
//int i = 1/0;
//加钱
ad.increaseMoney(to, money);
}*/
@Override
public void transfer( final Integer from,final Integer to,final Double money) {
// TODO Auto-generated method stub
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
//减钱
ad.decreaseMoney(from, money);
//加钱
ad.increaseMoney(to, money);
}
});
//1.打开事务
//2.调用doInTransactionWithoutResult方法
//3.提交事务
}
}
测试:
package cn.hncu.tx;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.hncu.service.AccountService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Demo2 {
@Resource(name="accountService")
private AccountService as;
@Test
public void fun1(){
as.transfer(1, 2, 100d);
}
}