事务管理
Spring提供了编码式和声明式事务管理的支持。
编码式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)用助于用户将操作与事务解耦。
选择编码式还是声明式在很大程度上是在细粒度控制和易用性之间权衡。
Spring并不直接管理事务,而是提供多种事务管理器,将它们事务管理职责委托给JTA或其他持久化机制所提供的平台相关的事务实现。每个事务管理器都会充当某一特定平台的事务实现的门面,这使得用户在Spring中使用事务时,不用关注事务的实际实现是什么。
JDBC事务
<bean
id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property
name="dataSource"
ref="dataSource"></property>
</bean>
Hibernate事务
<bean
id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property
name="sessionFactory"
ref="sessionFactory"></property>
</bean>
Spring对声明式的事务是通过AOP框架来完成。
声明式事务是通过事务属性来定义的,事务属性描述了事务策略如何应用到方法上,事务属性包括5个方面:传播行为、隔离级别、是否只读、事务超时、回滚规则。
传播行为:定义了客户端与被调用方法之间的事务边界。
隔离级别:一个事务可能受其它并发事务的影响程度。
在并发事务中可能会出现脏读、不可重复度、幻读的数据操作问题,因此要求并发事务之间隔离。隔离级别:
是否只读:事务对后端的数据库进行只读操作,数据库可以利用事务的只读特性来进行一些特定的优化。
事务超时:如果一个事务执行的时间太长,就会导致占用资源,因此,我们通常设定一个事务超时时间,当超过这个时间,就会导致事务超时,那么事务就会回滚。
回滚规则:事务在默认时遇到运行时异常就会回滚,而检查时异常不会回滚。我们也可以设定在遇到特定检查时异常回滚来定义自己的回滚规则。
在XML中通过tx命名空间来定义事务通知
<tx:advice
id="txAdvice">
<tx:attributes
>
<tx:method
name=""
isolation="DEFAULT"/>
<tx:method
name=""
no-rollback-for=""/>
<tx:method
name=""
propagation="REQUIRED"/>
<tx:method
name=""
read-only="false"/>
<tx:method
name=""
timeout="-1"/>
</tx:attributes>
</tx:advice>
//name表示与事务属性相关联的方法
<tx:advice>声明一个事务,<tx:attributes>定义事务的属性
在我们声明事务的同时,还需要使用事务管理器:
<tx:adviceid="txAdvice" transaction-manager="transactionManager">
………..
</tx:advice>
到现在我们只是定义了事务通知,我们还应该声明哪些Bean应该被通知,因此我们就需要通过AOP切点来完成:
<aop:config>
<aop:advisor
advice-ref="teAdvice"
pointcut="exectution(*bean.User.*(..))"/>
</aop:config>
到现在为止我们已经完全了解了声明式事务方法。
我们同样可以通过注解来简化我们的XML的事务,我们只需要在XML中使用:<tx:annotation-driven transaction-manager="txManager"/>
然后在Bean上注解@Transactional,事务属性是通过注解的属性来完成,对于每一个@Transactional注解的Bean,<tx:annotation-driven/>会自动为其添加事务通知。
实例一:
<bean
id="t"
class="test.Test01"></bean>
<bean
id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="driverClassName"
value="com.mysql.jdbc.Driver ">
</property>
<property
name="url"
value="jdbc:mysql://localhost:3306/dataBase">
</property>
<property
name="username"
value="root"></property>
<property
name="password"
value=""></property>
</bean>
<bean
id="jdbcTemplate"
class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg
ref="dataSource"></constructor-arg>
</bean>
<bean
id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property
name="dataSource"
ref="dataSource"></property>
</bean>
<tx:advice
id="txAdvice"transaction-manager="transactionManager">
<tx:attributes
>
<tx:method
name="*"
propagation="SUPPORTS"/>
<tx:method
name=""
read-only="false"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor
advice-ref="txAdvice"
pointcut=" execution(**..Test01.update(..)) "/>
</aop:config>
public
class Test01 {
public SimpleJdbcTemplategetSimpleJdbcTemplate() {
ApplicationContext ac=newClassPathXmlApplicationContext("applicationContext.xml");
SimpleJdbcTemplate stj=ac.getBean("jdbcTemplate",SimpleJdbcTemplate.class);
return stj;
}
public
intupdate(String sql)
{
return
this.getSimpleJdbcTemplate().update(sql);
}
public
static voidmain(String[] args) {
Test01 t=new Test01();
SimpleJdbcTemplate stj=t.getSimpleJdbcTemplate();
String insertsql="insertinto users values(10,‘lisi‘,2)";
introw=t.update(insertsql);
System.out.println(row);}
}
实例二:
<bean
id="t"
class="test.Test01"></bean>
<bean
id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="driverClassName"
value="com.mysql.jdbc.Driver ">
</property>
<property
name="url"
value="jdbc:mysql://localhost:3306/dataBase">
</property>
<property
name="username"
value="root"></property>
<property
name="password"
value=""></property>
</bean>
<bean
id="jdbcTemplate"
class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg
ref="dataSource"></constructor-arg>
</bean>
<bean
id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property
name="dataSource"
ref="dataSource"></property>
</bean>
<tx:annotation-driven
transaction-manager="transactionManager"/>
</beans>
@Transactional(propagation=Propagation.SUPPORTS,readOnly=false)
public
intupdate(String sql)
{
return
this.getSimpleJdbcTemplate().update(sql);
}