在本系列文章的《MyBatisSpring集成示例续》中,介绍了Spring的编程式事务管理。网友 dabing69221提出讲一下MyBatisSpring整合的声明式事务管理,今天就根据这一知识点,对上文的示例进行改进。

Spring的声明式事务管理是采用AOPAspect-Oriented Programming,面向切面编程)实现的。在编程式事务管理中,各事务处理代码实际上是相似的,这就造成了代码重复;而且编程式事务管理会造成事务管理代码和被管理的代码耦合,不符合软件工程中“高内聚、低耦合”的要求。若采用AOP,则可以避免以上缺陷。

Spring AOP需要引入的jar包请参考:http://blog.csdn.net/a352193394/article/details/7588851

首先写一个DAO类,代码如下:

package com.abc.dao;
import com.abc.mapper.StudentMapper;
import com.abc.domain.Student;
public class StudentDao {
private StudentMapper studentMapper;
//studentMapper的setter和getter方法
public void setStudentMapper(StudentMapper studentMapper)
{
this.studentMapper = studentMapper;
}
public StudentMapper getStudentMapper()
{
return this.studentMapper;
}
public void save(Student student)
{
this.studentMapper.add(student);
int a = 1 / 0;
}
}

在此类中,有一个save方法用于保存学生,当然也可以添加其他方法。

接下来,我们要在Spring中应用AOP此类的方法提供事务管理,其配置如下(beans.xml):

<?xml version="1.0" encoding="utf8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byName" default-lazy-init="false">
<!--本示例采用DBCP连接池,应预先把DBCP的jar包复制到工程的lib目录下。
连接池配置如下-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost/courseman"/>
<property name="username" value="courseman"/>
<property name="password" value="abc123"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--dataSource属性指定要用到的连接池-->
<property name="dataSource" ref="dataSource"/>
<!--configLocation属性指定mybatis的核心配置文件-->
<property name="configLocation" value="resources/configuration.xml"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="parentMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
abstract="true">
<!--sqlSessionFactory属性指定要用到的SqlSessionFactory实例-->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="studentMapper" parent="parentMapper">
<!--mapperInterface属性指定映射器接口,用于实现此接口并生成映射器对象-->
<property name="mapperInterface" value="com.abc.mapper.StudentMapper" />
</bean>
<!--为studentDao注入studentMapper-->
<bean id="studentDao" class="com.abc.dao.StudentDao">
<property name="studentMapper" ref="studentMapper" />
</bean>
<!--配置事务处理策略,transaction-manager属性指定事务管理器。
若事务管理器bean的id即为transactionManager,则
transaction-manager的属性可以不指定-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--所有以find开头的方法都是只读的-->
<tx:method name="find*" read-only="true" />
<tx:method name="save*" />
<!--其他方法使用默认事务策略-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- AOP配置-->
<aop:config>
<!--pointcut元素定义一个切入点,execution中的第一个星号
用以匹配方法的返回类型,这里星号表明匹配所有返回类型。
com.abc.dao.*.*(..)表明匹配com.abc.dao包下的所有类的所有
方法-->
<aop:pointcut id="myPointcut"
expression="execution(* com.abc.dao.*.*(..))" />
<!--将定义好的事务处理策略应用到上述的切入点-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" />
</aop:config>
</beans>

由以上可看出,事务策略的配置主要是<tx:method />标签的配置。其中name属性是必须的,用以指定事务策略作用的目标方法。除read-only属性外,还有propagationrollback-for等属性,用以指定事务的传播属性和触发事务回滚的异常。这里没有指定rollback-for属性,则Spring默认情况下只在发生了RuntimeExceptionError异常时,才回滚事务。

<aop:pointcut/>配置中,出现了execution表达式。关于此表达式的写法,请参考:http://lavasoft.blog.51cto.com/62575/172292/

StudentDaosave方法中,故意添加了一行代码int a = 1 / 0。这行代码会抛出ArithmeticException(这是一个RuntimeException),按照以上的配置,Spring会回滚事务。执行结果如下图所示:

003906886.png

如图中所示,事务已回滚,到数据库查询,学生记录也没有被插入。

本示例×××:http://down.51cto.com/data/857171

     猛戳这里全面系统地学习MyBatis 3

     MyBatis技术交流群:188972810,或扫描二维码:

wKioL1SaztmBchKiAADsv4YAWBY259.jpg


【MyBatis学习笔记】系列之预备篇一:ant的下载与安装

【MyBatis学习笔记】系列之预备篇二:ant入门示例

【MyBatis学习笔记】系列之一:MyBatis入门示例

【MyBatis学习笔记】系列之二:MyBatis增删改示例

【MyBatis学习笔记】系列之三:MyBatis的association示例

【MyBatis学习笔记】系列之四:MyBatis association的两种形式

【MyBatis学习笔记】系列之五:MyBatis与Spring集成示例

【MyBatis学习笔记】系列之六:MyBatis与Spring集成示例续

【MyBatis学习笔记】系列之七:MyBatis一对多双向关联

【MyBatis学习笔记】系列之八:MyBatis MapperScannerConfigurer配置

【MyBatis学习笔记】系列之九:MyBatis collection的两种形式

【MyBatis学习笔记】系列之十:MyBatis日志之Log4j示例

【MyBatis学习笔记】系列之十一:MyBatis多参数传递之注解方式示例

【MyBatis学习笔记】系列之十二:MyBatis多参数传递之默认命名方式示例

【MyBatis学习笔记】系列之十三:MyBatis多参数传递之Map方式示例

【MyBatis学习笔记】系列之十四:MyBatis中的N+1问题

【MyBatis学习笔记】系列之十五:MyBatis多参数传递之混合方式

【MyBatis学习笔记】系列之十六:Spring声明式事务管理示例

【MyBatis学习笔记】系列之十七:MyBatis多对多保存示例

【MyBatis学习笔记】系列之十八:MyBatis多对多关联查询示例

【MyBatis学习笔记】系列之十九:如何在MyBatis-3.2.7中使用Log4j2 rc2

MyBatis中如何通过继承SqlSessionDaoSupport来编写DAO(一)

MyBatis中如何通过继承SqlSessionDaoSupport来编写DAO(二)