Spring事务管理:Spring通过以下三种方式自实现对事务的管理(事务本来是在Dao层的概念,但是业务层调用Dao,所以业务层调用Dao时也需要使用事务)
1)使用Spring的事务代理工厂管理事务
2)使用Spring的事务注解管理事务
3)使用AspectJ的AOP配置管理事务
Spring事务管理API
1)事务管理接口:PlatFormTransactionManager接口对象(事务管理器)
用于完成事务的提交、回滚以及获取事务的状态信息
常用的实现类:
DataSourceTransactionManager:使用JDBC或者ibatis进行持久化数据时使用
HibernateTransactionManager:使用Hibernate进行持久化
Spring事务的默认回滚方式是:
发生运行时异常
(RuntimeException,/0,下标越界,程序无法处理)
回滚,发生受查异常(程序可以处理,继承自Exception)时提交。对于也可以受查异常,也可以设置其回滚方式(运行时异常严重)
2)事务定义接口TransactionDefinition:
定义了五事务隔离级别常量:ISOLATION_DEFAULT...
定义了七个事务传播行为常量:PROPAGATION_
指的是不同事务的方法在相互调用时的情况
a)
REQUIRED(默认值):该传播行为加载doOther上,
如果doSome调用doOther时就是在事务内运行的,则doOther加入到doSome的事务中;
如果doSome方法没有在事务内执行,则
doOther创建一个事务(doOther内beginTransaction endTransaction)并在其中执行
b)SUPPORT:
如果doSome有事务,doOther在doSome事务下运行
doSome没有事务,doOther可以在没有事务下运行
c)MANDATORY:
指定的方法必须在当前事务内执行,若当前没有事务则doOther抛出异常
d)REQUIRES_NEW:
总是新建一个事务,若当前存在事务,将当前事务挂起,直到新事务提交
e)NOT_SUPPORTED
doSome有事务,将doSome事务
挂起,doOther在无事务下运行
doSome没有事务,doOther直接在无事务下运行。
f)NEVER:
指定的方法不能在事务下运行
g)NESTED:指定的方法必须在事务内运行
doSome有事务,doOther内开启事务,doSome的事务不挂起
doSome无事务,doOther内beginTransaction,endTransaction
定义了默认事务超时时限:
常量TIMEOUT_DEFAULT定义了事务底层默认的超时时限。一般使用默认值
BuyStockService项目:
1)使用Spring的事务代理工厂bean管理事务 : 即
serviceImpl的代理,将事务添加到service中,将service调用的Dao方法绑定在一个事务中(AOP!),即serviceImpl的方法前后加上begin transcation 和 commit
<!-- 注册事务管理器 -->
<
bean
id
=
"TransactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
<
property
name
=
"dataSource"
ref
=
"c3p0Source"
/>
</
bean
>
<!-- 生成service的事务代理对象,在连接点上切入事务而不污染代码 -->
<
bean
id
=
"servicProxy"
class
=
"org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
<!-- 目标对象 -->
<
property
name
=
"target"
ref
=
"buyStockService"
/>
<
property
name
=
"transactionManager"
ref
=
"TransactionManager"
/>
<!-- 这里指明的是在 连接点 方法上要应用什么 事务属性 -->
<
property
name
=
"transactionAttributes"
>
<
props
>
//在open*匹配的方法上使用这个事务属性
<
prop
key
=
"open*"
>
ISOLATION_DEFAULT,PROPAGATION_REQUIRED
</
prop
>
<
prop
key
=
"buyStock"
>
ISOLATION_DEFAULT,PROPAGATION_REQUIRED
</
prop
>
</
props
>
</
property
>
默认的是发生 受查异常
提交,所以做以下配置:
<
prop
key
=
"buyStock"
>
ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-BuyStockException
</
prop
>
- 号的意思是回滚,意思是发生BuyStockException异常回滚
+是提交,如果+运行时异常,会提交
2)使用Spring的事务注解管理事务:需要使用事务的标签(约束)
<!-- 注册事务管理器 -->
<
bean
id
=
"TransactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
<
property
name
=
"dataSource"
ref
=
"c3p0Source"
/>
</
bean
>
<!-- 注册事务注解驱动 -->
<
tx:annotation-driven
transaction-manager
=
"TransactionManager"
/>
添加注解:
@Transactional
(isolation=Isolation.
DEFAULT
,propagation=Propagation.
REQUIRED
,rollbackFor=BuyStockException.
class
)
@Override
public
void
buyStock(String
aname
,
int
money
, String
sname
,
int
count
)
throws
BuyStockException{
//
TODO
Auto-generated method stub
Boolean
isBuy
=
true
;
adao
.updateAccount(
aname
,
money
,
isBuy
);
if
(
true
) {
throw
new
BuyStockException();
}
sdao
.updateStock(
sname
,
count
,
isBuy
);
}
3)使用AspectJ的XML配置管理事务(重点):导入两个JAR包
<!-- 注册事务管理器 -->
<
bean
id
=
"transactionManager"
class
=
"org.springframework.jdbc.datasource.DataSourceTransactionManager"
>
<
property
name
=
"dataSource"
ref
=
"c3p0Source"
/>
</
bean
>
<
tx:advice
id
=
"txAdvice"
transaction-manager
=
"transactionManager"
>
<
tx:attributes
>
<!-- 配置的是连接点方法的事务属性 -->
<
tx:method
name
=
"open*"
isolation
=
"DEFAULT"
propagation
=
"REQUIRED"
/>
<
tx:method
name
=
"buyStock"
isolation
=
"DEFAULT"
propagation
=
"REQUIRED"
rollback-for
=
"BuyStockException"
/>
</
tx:attributes
>
</
tx:advice
>
<!-- 使用AspectJ 的AOP-->
<
aop:config
>
<!-- 这里配置切入点,只有切入了才有效,这里为所有方法切入 -->
<
aop:advisor
advice-ref
=
"txAdvice"
pointcut
=
"execution(* *..service.*.*(..))"
/>
</
aop:config
>