声明式事务(注解)

spring声明事务的方式,使用注解的方式

@Transactional

⚫ 名称:@Transactional
⚫ 类型:方法注解,类注解,接口注解
⚫ 位置:方法定义上方,类定义上方,接口定义上方
⚫ 作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性
⚫ 范例:

@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {ArithmeticException.class, IOException.class},
noRollbackFor = {},
propagation = Propagation.REQUIRES_NEW
)

tx:annotation-driven 标签用于开启事务的注解驱动

⚫ 名称:tx:annotation-driven
⚫ 类型:标签
⚫ 归属:beans标签
⚫ 作用:开启事务注解驱动,并指定对应的事务管理器
⚫ 范例:

<tx:annotation-driven transaction-manager="txManager"/>

声明式事务(纯注解驱动)

@EnableTransactionManagement 这个注解就是代替上面的标签

⚫ 名称:@EnableTransactionManagement
⚫ 类型:类注解
⚫ 位置:Spring注解配置类上方
⚫ 作用:开启注解驱动,等同XML格式中的注解驱动
⚫ 范例:

@Configuration
@ComponentScan("com.fs")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class,MyBatisConfig.class,TransactionManagerConfig.class})
@EnableTransactionManagement
public class SpringConfig {}
public class TransactionManagerConfig {@Bean
public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){return new DataSourceTransactionManager(dataSource);
}
}

代码演示(代码中注释为详细解释)

数据表account

构建maven项目

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fs</groupId><artifactId>day04_spring_AOP_Transaction_02</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.1.9.RELEASE</version></dependency><!--        jdbc--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.9.RELEASE</version></dependency><!--        spring整合mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.1</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!--        mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--druid连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.20</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><!--        aop切面包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies></project>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.93.132:3306/test
jdbc.username=root
jdbc.password=root

编写配置类

SpringConfig

package com.fs.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;//表示这个类是一个spring的配置类,并将其存入到ioc容器中
@Configuration
/*开启扫描注解的那些包
<!--    启动spring扫描注解的包,只扫描spring的注解--><context:component-scan base-package="com.fs"/>*/
@ComponentScan("com.fs")
//引入其他的配置类
@Import({JdbcConfig.class,MybatisConfig.class,TransactionManagerConfig.class})
//开启切面自动代理
@EnableAspectJAutoProxy
//开启声明式事务管理    相当于配置文件中的 <tx:annotation-driven transaction-manager="transactionManager"/>
@EnableTransactionManagement
public class SpringConfig {}

JdbcConfig

package com.fs.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;/*
<!--    引入properties--><context:property-placeholder location="classpath:jdbc.properties"/>*/
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {//@Value("${Key}")@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;/*<!--    整合druid,把DruidDataSource交给spring管理--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>*///将返回的DruidDataSource交给ioc管理@Beanpublic DruidDataSource getDruidDataSource(){//创建DruidDataSourceDruidDataSource druidDataSource = new DruidDataSource();//给属性赋值,这个是上面从配置文件中依耐注入给属性的druidDataSource.setDriverClassName(driver);druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);//返回DruidDataSource,然后交给ioc管理return druidDataSource;}
}

MybatisConfig

package com.fs.config;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;import javax.sql.DataSource;public class MybatisConfig {/*<!--    配置MyBatis的会话工厂类  mybatis.spring 下的SqlSessionFactoryBean配置的sqlSessionFactory得到SqlSession,然后MyBatis从spring中拿到SqlSession.getMapper()去动态代理dao--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        给MyBatis配置链接池,依耐注入--><property name="dataSource" ref="dataSource"/>
<!--        配置别名扫描的包,被扫描的包下的类起的别名就是类名首字母小写,用于mapper.xml文件中使用--><property name="typeAliasesPackage" value="com.fs.pojo"/></bean>*/@Beanpublic SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){//创建sql会话工厂类                                //这里@Autowired也是从ioc拿DataSourceSqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();//从ioc容器中取出jdbcConfig中配置的druidDatasourcesqlSessionFactoryBean.setDataSource(dataSource);//配置起别名sqlSessionFactoryBean.setTypeAliasesPackage("com.fs.pojo");return sqlSessionFactoryBean;}/*<!--配置MyBatis扫描dao的包,让MyBatis动态代理生成这个dao的实现类,并交给ioc管理mybatis-spring这个包下MapperScannerConfigurer提供了spring于MyBatis的整合--><bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--        告诉MyBatis我dao在哪里.然后MyBatis将这个dao实现,然后给spring管理--><property name="basePackage" value="com.fs.dao"/></bean>*///创建MyBatis动态代理扫描类@Beanpublic MapperScannerConfigurer getMapperScannerConfigurer(){//创建映扫描配置类MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();//设置动态代理扫描的dao的包mapperScannerConfigurer.setBasePackage("com.fs.dao");//交给spring管理return mapperScannerConfigurer;}
}

TransactionManagerConfig

package com.fs.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;/*
声明式事务配置类*/
public class TransactionManagerConfig {/*<!--    将事务管理器交给ioc管理--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>*/@Beanpublic PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){//使用Spring的平台事务管理器,是一个接口,使用他的实现类构造器传递一个连接池DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();//传递一个连接池dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}

实体类

Account

package com.fs.pojo;import lombok.Data;@Data
public class Account {private Integer id;private String name;private Double money;
}

Dao

AccountDao

package com.fs.dao;import com.fs.pojo.Account;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;import java.util.List;public interface AccountDao {@Select("select * from account")List<Account> findAll();//查询所有//根据名字修改money@Update("UPDATE account SET money = #{money} WHERE name = #{name}")void transferMoney(Account account);//根据名字查询账户信息@Select("select * from account where name = #{name}")Account findAccountByName(@Param("name") String name);
}

service

AccountService

package com.fs.service;import com.fs.pojo.Account;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*
在接口上配置@Transactional,那么他下面的实现类都会进行事务管理
这个注解就相当于配置文件中的这些配置<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" read-only="false"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="pt" expression="execution(* com.fs.service.impl.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config>如果不写属性,该注解的默认配置为@Transactional(readOnly = false,timeout = -1,isolation = Isolation.DEFAULT,rollbackFor = {ArithmeticException.class, IOException.class},noRollbackFor = {},propagation = Propagation.REQUIRES_NEW)*/
public interface AccountService {List<Account> findAll();Account findAccountByName(String name);//对这个方法开启事务使用默认配置@Transactionalvoid transferMoneyAtoB(String aName,String bName,Integer money);
}

AccountServiceImpl

package com.fs.service.impl;import com.fs.dao.AccountDao;
import com.fs.pojo.Account;
import com.fs.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.sql.DataSource;
import java.util.List;/*<!--  把业务类 AccountServiceImpl 交给ioc管理 --><bean id="accountServiceImpl" class="com.fs.service.impl.AccountServiceImpl">
<!--       依耐注入dao,这个dao被MyBatis动态代理实现后被spring存放在ioc容器中--><property name="accountDao" ref="accountDao"/></bean>*/
@Service
public class AccountServiceImpl implements AccountService {//从ioc获取MyBatis动态代理的accountDao实现类@Autowiredprivate AccountDao accountDao;@Autowiredprivate DataSource dataSource;@Overridepublic List<Account> findAll() {return accountDao.findAll();}@Overridepublic Account findAccountByName(String name) {return accountDao.findAccountByName(name);}//转账的业务实现@Overridepublic void transferMoneyAtoB(String aName, String bName, Integer money) {//先查出两个人的数据Account aAccount = accountDao.findAccountByName(aName);Account bAccount = accountDao.findAccountByName(bName);//然后a减钱,b加钱aAccount.setMoney(aAccount.getMoney()-money);bAccount.setMoney(bAccount.getMoney()+money);//然后调用转账方法(sql语句为更新账户)accountDao.transferMoney(aAccount);//制作一个异常
//        int i = 1/0;accountDao.transferMoney(bAccount);}}

测试类

package com.fs.service.impl;import com.fs.config.SpringConfig;
import com.fs.pojo.Account;
import com.fs.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceImplTest {@Autowiredprivate AccountService accountService;//测试查询所有方法@Testpublic void findAll() {List<Account> all = accountService.findAll();System.out.println(all);}//测试转账方法已经使用@Transactional绑定事务@Testpublic void transferMoneyAtoB() {//测试转账方法accountService.transferMoneyAtoB("小付","小花",100);}}

执行效果

业务层转账方法正常运行成功后数据表数据

由于我们测试代码中是小付向小花转账100元,代码执行成功后应该小付900,小花1100

业务层转账方法我们给制作一个异常1/0 的/ by zero异常,
运存测试转账方法控制台输出

数据库中表的数据
小付原本900,小花1100,我们进行了转账业务,但是制作了异常,事务会进行回滚,所以金额不会发生变化

spring控制事务:声明式事务(注解)相关推荐

  1. spring控制事务:声明式事务(XML)事务的传播行为

    声明式事务(XML) 使用spring提供的专用于mybatis的事务管理器在xml中声明式事务 声明式事务需要使用到的标签 tx配置 进行<tx 标签的使用需要在xml头部导入命名空间 xml ...

  2. Spring源码——声明式事务流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  3. Spring的编程式事务声明式事务 基于注解的声明式事务控制

    文章目录 Spring中编程式事务 基于XML的声明式事务控制 基于注解的声明式事务控制 Spring集成web环境 Spring中编程式事务 Spring的事务控制可以分为编程式事务控制和声明式事务 ...

  4. Spring AOP实现声明式事务代码分析

    众所周知,Spring的声明式事务是利用AOP手段实现的,所谓"深入一点,你会更快乐",本文试图给出相关代码分析. AOP联盟为增强定义了org.aopalliance.aop.A ...

  5. spring+mybatis之声明式事务管理初识(小实例)

    前几篇的文章都只是初步学习spring和mybatis框架,所写的实例也都非常简单,所进行的数据访问控制也都很简单,没有加入事务管理.这篇文章将初步接触事务管理. 1.事务管理 理解事务管理之前,先通 ...

  6. JDBC事务和JTA事务的区别 --包含spring事务 声明式事务

    2019独角兽企业重金招聘Python工程师标准>>> 一.事务概述 事务表示一个由一系列的数据库操作组成的不可分割的逻辑单位,其中的操作要么全做要么全都不做. 与事务相关的操作主要 ...

  7. spring事物管理--声明式(AspectJ)注解实现 (推荐使用)

    1.表结构及数据 2.使用的jar包 3.service.Dao层接口与实现类: Dao接口: //转账案例持久层接口 public interface AccountDao {/*** @param ...

  8. spring——使用xml声明式事务整合jdbc——GRUD

    准备阶段: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  9. Spring+mybatis整合声明式事务异常之org.springframework.transaction.TransactionTimedOutException: Transaction ..

    1.异常信息 org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline ...

最新文章

  1. 统计学习II.7 广义线性模型1 指数分布族
  2. 白话Elasticsearch02- 结构化搜索之filter执行原理bitset机制与caching机制
  3. python numpy矩阵切片和索引的用法(冒号:和省略号...)
  4. 如何优化大规模推荐?下一代算法技术JTM来了
  5. c++ 字符串连接_C语言字符串操作总结大全(超详细)
  6. 2017年计算机基础知识答题宝典,最全全国计算机基础知识试题及答案考级宝典(2018)..pdf...
  7. 机器学习_回归和分类的区别
  8. 2020年最新中科院期刊分区表
  9. HTML练习4制作京东登录页,day4 CSS属性和京东登录
  10. html如何改成花体英文字体,花体英文转换器可复制字体(附花体字发文技巧)...
  11. 论文发表费用具体是多少
  12. 用于创建此对象的程序是 Equation。您的计算机尚未安装此程序或此程序无响应。 若要编辑此对象,请安装 Equation或确保 Equation中的任何对话框都已关闭
  13. 矩阵手册(六)—— Cauchy–Schwarz 不等式及其证明
  14. Andromeda:适用于多进程架构的组件通信框架
  15. HOW to BECOME a GOOD THEORETICAL PHYSICIST(转载的)
  16. Linux系统 | vim配置
  17. 使用adb连接夜神模拟器,查看多开模拟器端口号
  18. 葡萄牙晋级世界杯决赛
  19. 动态规划范例——驿站马车问题
  20. 餐饮行业私域社群营销的方案有哪些?

热门文章

  1. oracle 的行级触发器
  2. 《那些年啊,那些事——一个程序员的奋斗史》——61
  3. 同步模式下的端口映射程序
  4. Oracle学习(十三)优化专题 【持续更新】
  5. pwnable.tw unexploitable 分析
  6. 团队-团队编程项目作业名称-需求分析
  7. PHP学习笔记 - 进阶篇(7)
  8. android NDK 知识汇总
  9. (码友推荐)2018-07-12 .NET及相关开发资讯速递
  10. iOS html5使用缓存并及时更新方案总结