• Spring事务简介(案例:银行账户转账)


    目录

    事务简介 :

    银行账户转账代码实现:

    需求:

    分析:

    分析结果:

    一.解决办法(开启Spring事务管理步骤):

    1.在业务层接口上添加Spring事务管理

     2.设置事务管理器(在Spring jdbc配置文件中)

    3.开启注解式事务驱动

    二.代码实现:

    1.文件大致格式

    2.ServiceAdvise(上一章节的AOP,这一章节没有使用,在Spring配置类里面注释了)

    3.JdbcConfig(jdbc配置类)

    4.SpringConfig(Spring配置类)

    5.MyBatisConfig(MyBatis配置类)

    6.AccountDao(数据层接口)

    7.Account(实体类)

    8.AccountServiceImpl(业务层实现类)

    9.AccountService(业务层接口)

    10.jdbc.properties(jdbc配置信息)

    11.AccountServiceTest(测试类)

    12.pom.xml(Maven配置文件)


    事务简介 :

    事务作用:在数据层保障一系列的数据库操作同成功同失败(一致性)

    Spring事务:在数据层(dao)业务层(service)保障一系列的数据库操作同成功同失败

    进行保障的呢?(通过PlatformTransactionManager接口进行保障)

    PlatformTransactionManager接口

    1. public interface PlatformTransactionManager {
    2. @Override
    3. public TransactionStatus getTransaction(TransactionDefinition transactionDefinition) throws TransactionException {
    4. return null;
    5. }
    6. @Override
    7. public void commit(TransactionStatus transactionStatus) throws TransactionException {
    8. }
    9. @Override
    10. public void rollback(TransactionStatus transactionStatus) throws TransactionException {
    11. }
    12. }

    PlatformTransactionManager接口的实现类(DataSourceTransactionManager

    银行账户转账代码实现:

    需求:

    需求:实现任意两个账户之间的转账操作

    需求微缩:A账户减钱,B账户加钱

    ps:真正的银行转账有三个用户,a转b,b转c

    分析:

    1.数据层提供基础操作,指定账户减钱(outMoney),指定账户加钱(inmoney)

    2.业务层提供转账操作(transfer),调用减钱与加钱的操作

    3.提供两个账号和操作金额执行转账操作

    4.基于Spring整合MyBatis环境搭建上述操作

    分析结果:

    1.程序正常执行时,账户金额A加B减,程序正常

    2.程序出现异常之后,转账失败,但是异常之前的得操作成功,异常之后得操作失败,整体业务失败

    一.解决办法(开启Spring事务管理步骤):

    1.在业务层接口上添加Spring事务管理

    注意事项:

    1.Spring注解式事务通常添加在业务层接口中,而不会添加在业务层得实现类中,降低耦合

    2.注解式事务可以添加到业务层方法上,表示为此方法开启事务。也可以添加到业务层接口上,表示当前接口的所有方法都开启事务

    1. @Transactional
    2. void transfer(String out,String in ,Double money) ;

     2.设置事务管理器(在Spring jdbc配置文件中)

    注意事项:

    1.事务管理器要根据实现技术进行选择

    2.MyBtis框架使用的式Jdbc事务

    1. //事务管理器
    2. @Bean
    3. public PlatformTransactionManager transactionManager(DataSource dataSource){
    4. //一个bean需要外部资源怎么办,引用注入帮你解决问题
    5. DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    6. transactionManager.setDataSource(dataSource);
    7. return transactionManager;
    8. }

    3.开启注解式事务驱动

    1. package com.itheima.config;
    2. import org.springframework.context.annotation.*;
    3. import org.springframework.transaction.annotation.EnableTransactionManagement;
    4. @Configuration //代表了这是个配置类,以此与applicationContext.xml基础配置文件相当
    5. @ComponentScan("com.itheima") //包扫描
    6. @PropertySource("jdbc.properties") //加载properties配置文件
    7. @Import({JdbcConfig.class,MybatisConfig.class}) //加载JdbcConfig,MybatisConfig配置类
    8. //@EnableAspectJAutoProxy //启动AOP的注解,切面
    9. @EnableTransactionManagement //启动事务管理,加载相对应的事务
    10. public class SpringConfig {
    11. }

    二.代码实现:

    1.文件大致格式

    2.ServiceAdvise(上一章节的AOP,这一章节没有使用,在Spring配置类里面注释了)

    1. package com.itheima.aop;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.Signature;
    4. import org.aspectj.lang.annotation.Around;
    5. import org.aspectj.lang.annotation.Aspect;
    6. import org.aspectj.lang.annotation.Pointcut;
    7. import org.springframework.stereotype.Component;
    8. public class ServiceAdvise {
    9. //定义切入点,切入点时Service里面的所有方法,
    10. @Pointcut("execution(* com.itheima.service.*Service.*(..))")
    11. private void servicePt(){}
    12. //把切入点servicePt()与通知runSpeed()进行绑定
    13. @Around("ServiceAdvise.servicePt()")
    14. public void runSpeed(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    15. long star = System.currentTimeMillis();
    16. Signature signature = proceedingJoinPoint.getSignature();//代表了一次执行的签名信息
    17. String name = signature.getName(); //方法名
    18. Class declaringType = signature.getDeclaringType(); //表示方法的接口名
    19. for (int i = 0; i < 10000; i++) {
    20. proceedingJoinPoint.proceed();
    21. }
    22. Object proceed = proceedingJoinPoint.proceed();//调取原始操作,即时AccountServiceImpl的返回值
    23. long end = System.currentTimeMillis();
    24. System.out.println("业务层接口"+declaringType+"的"+name+"方法,执行万次的测试为"+(end - star)+"ms");
    25. }
    26. }

    3.JdbcConfig(jdbc配置类)

    1. package com.itheima.config;
    2. import com.alibaba.druid.pool.DruidDataSource;
    3. import org.springframework.beans.factory.annotation.Value;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    6. import org.springframework.transaction.PlatformTransactionManager;
    7. import javax.sql.DataSource;
    8. public class JdbcConfig {
    9. @Value("${jdbc.driver}")
    10. private String driver;
    11. @Value("${jdbc.url}")
    12. private String url;
    13. @Value("${jdbc.username}")
    14. private String username;
    15. @Value("${jdbc.password}")
    16. private String password;
    17. //1.定义一个方法获取响应的bean
    18. //2.添加@Bean,表示当前方法的返回值是一个bean
    19. @Bean
    20. public DataSource dataSource(){
    21. DruidDataSource ds = new DruidDataSource();
    22. ds.setDriverClassName(driver);
    23. ds.setUrl(url);
    24. ds.setUsername(username);
    25. ds.setPassword(password);
    26. return ds;
    27. }
    28. //事务管理器
    29. @Bean
    30. public PlatformTransactionManager transactionManager(DataSource dataSource){
    31. //一个bean需要外部资源怎么办,引用注入帮你解决问题
    32. DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    33. transactionManager.setDataSource(dataSource);
    34. return transactionManager;
    35. }
    36. }

    4.SpringConfig(Spring配置类)

    1. package com.itheima.config;
    2. import org.springframework.context.annotation.*;
    3. import org.springframework.transaction.annotation.EnableTransactionManagement;
    4. @Configuration //代表了这是个配置类,以此与applicationContext.xml基础配置文件相当
    5. @ComponentScan("com.itheima") //包扫描
    6. @PropertySource("jdbc.properties") //加载properties配置文件
    7. @Import({JdbcConfig.class,MybatisConfig.class}) //加载JdbcConfig,MybatisConfig配置类
    8. //@EnableAspectJAutoProxy //启动AOP的注解,切面
    9. @EnableTransactionManagement //启动事务管理,加载相对应的事务
    10. public class SpringConfig {
    11. }

    5.MyBatisConfig(MyBatis配置类)

    1. package com.itheima.config;
    2. import org.mybatis.spring.SqlSessionFactoryBean;
    3. import org.mybatis.spring.mapper.MapperScannerConfigurer;
    4. import org.springframework.context.annotation.Bean;
    5. import javax.sql.DataSource;
    6. public class MybatisConfig {
    7. //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    8. @Bean
    9. public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){//这里得DataSource是代表着引用注入,jdbcConfig
    10. SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
    11. ssfb.setTypeAliasesPackage("com.itheima.domain");//问实体类的位置,,扫描类型别名的包
    12. ssfb.setDataSource(dataSource);//替代的是jdbcConfig中的DataSource,也就是详细配置信息
    13. return ssfb;
    14. }
    15. //定义bean,返回MapperScannerConfigurer对象
    16. @Bean
    17. public MapperScannerConfigurer mapperScannerConfigurer(){
    18. MapperScannerConfigurer msc = new MapperScannerConfigurer();
    19. msc.setBasePackage("com.itheima.dao");//问映射在什么位置,由于注解完成了执行语句,所以不需要有映射文件
    20. return msc;
    21. }
    22. }

    6.AccountDao(数据层接口)

    1. package com.itheima.dao;
    2. import com.itheima.domain.Account;
    3. import org.apache.ibatis.annotations.*;
    4. import java.util.List;
    5. public interface AccountDao {
    6. @Insert("insert into account(username,password)values(#{username},#{password})")
    7. void save(Account account);
    8. @Delete("delete from account where id = #{id} ")
    9. void delete(Integer id);
    10. @Update("update account set username = #{username} , password = #{password} where id = #{id} ")
    11. void update(Account account);
    12. @Select("select * from account")
    13. List findAll();
    14. @Select("select * from account where id = #{id} ")
    15. Account findById(Integer id);
    16. @Update("update account set money = money + #{money} where name = #{name}")
    17. void inMoney(@Param("name") String name, @Param("money") Double money);
    18. @Update("update account set money = money - #{money} where name = #{name}")
    19. void outMoney(@Param("name") String name, @Param("money") Double money);
    20. }

    7.Account(实体类)

    1. package com.itheima.domain;
    2. import java.io.Serializable;
    3. public class Account implements Serializable {
    4. private Integer id;
    5. private String name;
    6. private Double money;
    7. public Integer getId() {
    8. return id;
    9. }
    10. public void setId(Integer id) {
    11. this.id = id;
    12. }
    13. public String getName() {
    14. return name;
    15. }
    16. public void setName(String name) {
    17. this.name = name;
    18. }
    19. public Double getMoney() {
    20. return money;
    21. }
    22. public void setMoney(Double money) {
    23. this.money = money;
    24. }
    25. @Override
    26. public String toString() {
    27. return "Account{" +
    28. "id=" + id +
    29. ", name='" + name + '\'' +
    30. ", money=" + money +
    31. '}';
    32. }
    33. }

    8.AccountServiceImpl(业务层实现类)

    1. package com.itheima.service.impl;
    2. import com.itheima.dao.AccountDao;
    3. import com.itheima.domain.Account;
    4. import com.itheima.service.AccountService;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.stereotype.Service;
    7. import java.util.List;
    8. @Service
    9. public class AccountServiceImpl implements AccountService {
    10. @Autowired
    11. private AccountDao accountDao;
    12. @Override
    13. public void save(Account account) {
    14. accountDao.save(account);
    15. }
    16. @Override
    17. public void update(Account account){
    18. accountDao.update(account);
    19. }
    20. @Override
    21. public void delete(Integer id) {
    22. accountDao.delete(id);
    23. }
    24. @Override
    25. public Account findById(Integer id) {
    26. return accountDao.findById(id);
    27. }
    28. @Override
    29. public List findAll() {
    30. return accountDao.findAll();
    31. }
    32. @Override
    33. public void transfer(String out, String in, Double money) {
    34. accountDao.outMoney(out,money);
    35. int i = 1/0;
    36. accountDao.inMoney(in,money);
    37. }
    38. }

    9.AccountService(业务层接口)

    1. package com.itheima.service;
    2. import com.itheima.domain.Account;
    3. import org.springframework.transaction.annotation.Transactional;
    4. import java.util.List;
    5. public interface AccountService {
    6. void save(Account account);
    7. void delete(Integer id);
    8. void update(Account account);
    9. List findAll();
    10. Account findById(Integer id);
    11. @Transactional
    12. void transfer(String out,String in ,Double money) ;
    13. }

    10.jdbc.properties(jdbc配置信息)

    1. jdbc.driver=com.mysql.jdbc.Driver
    2. jdbc.url= jdbc:mysql://localhost:3306/db1?useSSL=false
    3. jdbc.username=root
    4. jdbc.password=root

    11.AccountServiceTest(测试类)

    1. package com.itheima.service;
    2. import com.itheima.config.SpringConfig;
    3. import org.junit.Test;
    4. import org.junit.runner.RunWith;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.test.context.ContextConfiguration;
    7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    8. @RunWith(SpringJUnit4ClassRunner.class) //设置专用的类运行器
    9. @ContextConfiguration(classes = SpringConfig.class) //指定Spring文件的配置类
    10. public class AccountServiceTest {
    11. @Autowired
    12. private AccountService accountService;
    13. @Test
    14. public void testFindById(){
    15. System.out.println(accountService.findById(2));
    16. }
    17. @Test
    18. public void testFindAll(){
    19. System.out.println(accountService.findAll());
    20. }
    21. @Test
    22. public void testTransfer() {
    23. accountService.transfer("刘德华","周杰伦",100D);
    24. }
    25. }

    12.pom.xml(Maven配置文件)

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <groupId>org.examplegroupId>
    7. <artifactId>Spring-demo1-lifeCycleartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <properties>
    10. <maven.compiler.source>18maven.compiler.source>
    11. <maven.compiler.target>18maven.compiler.target>
    12. properties>
    13. <dependencies>
    14. <dependency>
    15. <groupId>org.springframeworkgroupId>
    16. <artifactId>spring-contextartifactId>
    17. <version>5.3.23version>
    18. dependency>
    19. <dependency>
    20. <groupId>javax.annotationgroupId>
    21. <artifactId>javax.annotation-apiartifactId>
    22. <version>1.3.2version>
    23. dependency>
    24. <dependency>
    25. <groupId>com.alibabagroupId>
    26. <artifactId>druidartifactId>
    27. <version>1.2.11version>
    28. dependency>
    29. <dependency>
    30. <groupId>org.mybatisgroupId>
    31. <artifactId>mybatisartifactId>
    32. <version>3.5.6version>
    33. dependency>
    34. <dependency>
    35. <groupId>mysqlgroupId>
    36. <artifactId>mysql-connector-javaartifactId>
    37. <version>5.1.46version>
    38. dependency>
    39. <dependency>
    40. <groupId>org.springframeworkgroupId>
    41. <artifactId>spring-jdbcartifactId>
    42. <version>5.0.0.RELEASEversion>
    43. dependency>
    44. <dependency>
    45. <groupId>org.mybatisgroupId>
    46. <artifactId>mybatis-springartifactId>
    47. <version>1.3.0version>
    48. dependency>
    49. <dependency>
    50. <groupId>junitgroupId>
    51. <artifactId>junitartifactId>
    52. <version>4.12version>
    53. <scope>testscope>
    54. dependency>
    55. <dependency>
    56. <groupId>org.springframeworkgroupId>
    57. <artifactId>spring-testartifactId>
    58. <version>5.2.10.RELEASEversion>
    59. dependency>
    60. <dependency>
    61. <groupId>org.aspectjgroupId>
    62. <artifactId>aspectjweaverartifactId>
    63. <version>1.8.8version>
    64. dependency>
    65. dependencies>
    66. project>
  • 相关阅读:
    springmvc、springBoot---第三篇
    c语言基础:L1-057 PTA使我精神焕发
    MATLAB中fillmissing函数用法
    SpringBoot+Vue搭建Admin管理系统
    mysql查询速度 limit 1000,10 和limit 10 一样快吗?
    PostgreSQL部署与配置
    ARM:使用汇编完成三个灯流水亮灭
    核货宝:服装店收银系统如何选择?收银系统选购指南!
    【数字通信原理】第五章 基带传输理论
    GEE:根据影像最小值和最大值自适应可视化参数设置
  • 原文地址:https://blog.csdn.net/qq_51272114/article/details/127834039