使用@Transactional注解完成事务控制,此注解可添加到类上,则对类中所有方法执行事务的设定,注解添加到方法上,则对该方法执行事务处理
@Transactional(...)注解参数说明:
注意:当一个类中有较多方法时,对方法进行一对一的注解式事务管理太多繁琐,简单演示事务特性时可以使用注解式事务,在实际项目中不常用
在配置文件中添加一次,整个项目遵循该事务的设定,是Spring常用的,也是非常有名的事务处理方式
要求项目中的方法命名有规范,例如:
添加操作包含:add,save,insert,set等
更新操作包含:update,change,modify等
删除操作包含:delete,drop,remove,clear等
查询操作包含:select,find,search,get等
配置事务切面时,可以使用通配符来匹配满足通配条件的方法
<!-- 此配置文件和applicationContext_service.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 导入applicationContext_mapper.xml --> <import resource="applicationContext_mapper.xml"/> <!-- 添加包扫描 --> <context:component-scan base-package="com.example.service.impl"/> <!-- 添加事务管理器 --> <bean id="transactionManager" > <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置事务切面 --> <tx:advice id="myadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*select*" read-only="true"/> <tx:method name="*search*" read-only="true"/> <tx:method name="*find*" read-only="true"/> <tx:method name="*get*" read-only="true"/> <tx:method name="*update*" propagation="REQUIRED"/> <tx:method name="*save*" propagation="REQUIRED"/> <tx:method name="*modify*" propagation="REQUIRED"/> <tx:method name="*set*" propagation="REQUIRED"/> <tx:method name="*insert*" propagation="REQUIRED"/> <tx:method name="*delete*" propagation="REQUIRED"/> <tx:method name="*remove*" propagation="REQUIRED"/> <tx:method name="*clear*" propagation="REQUIRED"/> <tx:method name="*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!-- 绑定切面和切入点 --> <aop:config> <!-- 定义切入点表达式 --> <aop:pointcut id="mycut" expression="execution(* com.example.service.impl.*.*(..))"/> <!-- 将切面和切入点表达式绑定,为目标业务实现类中的业务方法提供对应的事务切面功能 --> <aop:advisor advice-ref="myadvice" pointcut-ref="mycut"/> </aop:config></beans>package com.example.service.impl;import com.example.mapper.UserMapper;import com.example.pojo.Account;import com.example.pojo.User;import com.example.service.AccountService;import com.example.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * 业务实现类 */@Servicepublic class UserServiceImpl implements UserService { //业务逻辑层实现类持有数据访问层的接口类型的变量 @Autowired UserMapper userMapper; //持有Account业务逻辑层的接口类型的变量 @Autowired AccountService accountService; @Override public int insert(User user) { int num = userMapper.insert(user); if(num == 1){ System.out.println("用户导入成功!"); }else{ System.out.println("用户导入失败!"); } //嵌套调用账户的业务逻辑功能 accountService.save(new Account(25, "荷包蛋6","富婆的账户6")); return num; }}package com.example.test;import com.example.pojo.User;import com.example.service.UserService;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUserAndAccount { @Test public void testUserAndAccount(){ //创建Spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_trans.xml"); //获取用户的业务逻辑层对象 UserService userService = (UserService) ac.getBean("userServiceImpl"); //调用业务功能 userService.insert(new User(2, "荷包蛋2", "hanzhanghan2")); }}

<tx:method name="*save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/><tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
如果当声明式注解所规划的事务管理和某个业务层的业务方法对事务的个性化需求相冲突时,可以再另外开启注解式事务并设置两种事务的优先级,达到优先使用注解式事务的目的。当order属性的值越大,事务的优先级越高
<!-- 添加注解式事务驱动--> <tx:annotation-driven order="10" transaction-manager="transactionManager"/> <aop:advisor order="1" advice-ref="myadvice" pointcut-ref="mycut"/>
不同技术对事务提交和回滚的实现简单列举如下,可见不同的技术使用的数据库操作对象不同
JDBC:Connection con.commit(); con.rollback();
MyBatis:SqlSession sqlSession.commit(); sqlSession.rollback();
Hibernate:Session session.commit(); session.rollback();
使用事务管理器,目的就是为了生成相应技术下的数据库连接 + 执行语句的对象
如果使用MyBatis框架,必须使用DataSourceTransactionManager类完成处理
<!-- 添加事务管理器 --> <bean id="transactionManager" > <!-- 由于事务管理必然要涉及到数据库的操作,例如数据回滚等等,所以必须添加数据源配置 --> <property name="dataSource" ref="dataSource"/> </bean>