您的位置:首页 > 编程语言 > Java开发

Spring-事务处理

2016-05-30 23:54 423 查看
原始JDBC实现事务的代码如果是通过切面实现,大概是下面这样的。
public void transferMoney(){
try{
//@Before
conn = dataSource.getConnection(); //每个事务Connection需要独立
conn.setAutoCommit(false);

//ProceedingJoinPoint.proceed()
//实现事务中的业务逻辑操作

//@AfterReturning
conn.commit();//正常执行完事务后提交
}catch(SQLException e){
//@AfterThrowing
e.printStackTrace();
if(conn != null){
try{
conn.rollback(); //回滚未完成的数据库操作
}catch(SQLException e){
..
}
}
}finally{
//@After 后置通知
if(conn!=null){
try{
conn.cloes();
}catch(SQLException e){
...
}
}
}
}

使用Spring执行事务步骤:

1.配置事务管理器
<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

2.启用事务注解(需要加入tx命名空间)
<tx:annotation-driven transaction-manager="transactionManager"/>

3.添加@Transactional注解

只需要在需要使用事务的函数上面添加注解,即可。

@Transactional

public void transferMoney(){}

事务的传播属性

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。

是继续在现有的事务中运行,还是开启一个新的事务等。

Spring定义了7种传播行为(用枚举实现):注意上面提到Transactional是修饰方法的,下面的情况都是对当前执行的方法的说明。

REQUIRED(默认) :如果有一个既有的事务,则调用新方法则继续使用已有的的事务。若没有则开启新事务。

REQUIRED_NEW:如果有新的事务,则新方法会将其挂起。并开启自己的事务。

后面几个不常用

SUPPORTS:如果有事务在运行,则当前方法在这个事务内运行,否则可以不在事务中运行。

NOT_SUPPORED:当前方法不支持,若有事务在运行,则将其挂起。

MANDATORY:当前方法必须运行在事物内部,如果没有正在运行的事务则异常。

NEVER:当前方法不运行在事务中,若有运行的事务则抛出异常。

NESTED:若有事务在运行,当前方法就应该在这个事务中嵌套事务内运行,否则就启动一个新的事务,并在他自己的事务内运行。

@Transactional(propagation=Propagation.REQUIRED)

public void transferAll(){
transferMoney(); //transferAll本身是有事务的,但是transferMoney也是有事务的,这种情况就适合上面描述的传播方式啦。

}

事务的其他特性

隔离级别: isolation=Isolation.READ_COMMITTED

指定回滚异常、不会滚异常(默认只有运行时异常回滚),也可以进行特殊的设置。

运行时异常不回滚设置例:@Transactional(noRollbackFor={RuntimeException.class})

指定事务是否可以更改数据:@Transactional(readOnly=true) 设置为true时,会被优化为无锁,相当于不使用事务。
指定timeout时间(单位是秒):@Transactional(timeout=1)指定回滚前到超时时间。

用xml配置事务

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.2.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.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <context:property-placeholder location="c3p0.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="initialPoolSize"  value="${initialPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
</bean>
<!-- 配置JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</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="transferMoney" propagation="REQUIRED" isolation="DEFAULT" read-only="false" timeout="-1" />
</tx:attributes>
</tx:advice>

<!-- 3.配置事务切入点,关联切入点和事务 -->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(public void test.DbTransaction.transferMoney())"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
</beans>


<完>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: