• Spring中的事务管理


    事务的概念

    事务:是数据库操作最基本单位,逻辑上的一组操作,要么都成功,如果有一个失败所有操作都失败。

    事务的四大特性:

    1. 原子性
    2. 一致性
    3. 隔离性
    4. 持久性

    使用代码开启事务的过程(一共分为4步):

    1. public void accountMoney(){
    2. try {
    3. //1.手动开启事务
    4. //2.编写业务逻辑
    5. // userDao.addMoney();
    6. // userDao.reduceMoney();
    7. //3.没有发生异常,提交事务
    8. } catch (Exception e) {
    9. //4.发生异常,事务回滚
    10. e.printStackTrace();
    11. }
    12. }

            在JavaEE的开发中主要包含三层结构:controller层(web层)、service层(业务层)、dao层,一般事务添加到业务层(service层)上

            在spring进行事务的管理主要分为两种方式:编程式事务管理和声明式事务管理,一般常用的是声明式事务管理,下面将介绍声明式事务管理。

    声明式事务管理有两种实现方式:

    1. 基于注解的方式
    2. 基于xml配置文件方式

            这篇博客主要讲解三大部分:①基于xml配置文件和注解的混合方式,②基于完全xml配置文件的方式,③基于完全注解的方式

            在Spring进行事务声明式事务管理,底层使用的AOP。

    目录

    1、基于xml配置文件和注解的混合方式

    1.1、Spring事务管理API

    1.2、在pom文件中引入相关依赖

    1.3、在xml文件中完成一系列的配置

    1.4、在service类上面添加事务注解

    1.5、编写测试类进行测试

    1.6、得到运行结果

    2、基于完全xml配置文件的方式

    2.1、引入相关的依赖

    2.2、在xml文件中进行配置

    2.3、编写业务逻辑代码

    2.4、测试代码的编写

    2.5、得到运行结果

    3、基于完全注解的方式

    3.1、在pom文件中添加相关依赖

    3.2、编写配置类TestConfig

    3.3、编写业务逻辑代码

    3.4、编写测试类

    3.5、得到测试运行结果

    4、总结


    1、基于xml配置文件和注解的混合方式

    1.1、Spring事务管理API

            提供接口PlatformTransactionManager ,接口 PlatformTransactionManage 代表事务管理器,这个接口针对不同的框架提供不同的实现类 (接口 PlatformTransactionManager),其中在spring中以及Mybatis中使用的都是 实现类DataSourceTransactionManager,而Hibernate中使用的是实现类HibernateTransactionManager

    1.2、在pom文件中引入相关依赖

            在依赖引入的时候,要注意每个以来版本之间是否会有冲突,即有没有兼容的问题,不兼容的话,会爆上一篇博客的错误。地址:Error creating bean with name ‘userService‘ defined in file [D:\ajavaproject\coding\atguiguLearnSpri_网恋褙骗八万的博客-CSDN博客

    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. <packaging>warpackaging>
    6. <parent>
    7. <artifactId>atguiguLearnSpring5artifactId>
    8. <groupId>org.examplegroupId>
    9. <version>1.0-SNAPSHOTversion>
    10. parent>
    11. <modelVersion>4.0.0modelVersion>
    12. <artifactId>Spring5_demo6artifactId>
    13. <dependencies>
    14. <dependency>
    15. <groupId>com.alibabagroupId>
    16. <artifactId>druidartifactId>
    17. <version>1.1.10version>
    18. dependency>
    19. <dependency>
    20. <groupId>mysqlgroupId>
    21. <artifactId>mysql-connector-javaartifactId>
    22. <version>5.1.6version>
    23. dependency>
    24. <dependency>
    25. <groupId>org.springframeworkgroupId>
    26. <artifactId>spring-aopartifactId>
    27. <version>5.0.2.RELEASEversion>
    28. dependency>
    29. <dependency>
    30. <groupId>org.springframeworkgroupId>
    31. <artifactId>spring-contextartifactId>
    32. <version>5.0.2.RELEASEversion>
    33. dependency>
    34. <dependency>
    35. <groupId>org.springframeworkgroupId>
    36. <artifactId>spring-txartifactId>
    37. <version>5.0.2.RELEASEversion>
    38. dependency>
    39. <dependency>
    40. <groupId>org.springframeworkgroupId>
    41. <artifactId>spring-coreartifactId>
    42. <version>5.0.2.RELEASEversion>
    43. dependency>
    44. <dependency>
    45. <groupId>org.springframeworkgroupId>
    46. <artifactId>spring-jdbcartifactId>
    47. <version>5.0.2.RELEASEversion>
    48. dependency>
    49. <dependency>
    50. <groupId>org.springframeworkgroupId>
    51. <artifactId>spring-ormartifactId>
    52. <version>5.0.2.RELEASEversion>
    53. dependency>
    54. <dependency>
    55. <groupId>org.springframeworkgroupId>
    56. <artifactId>spring-aspectsartifactId>
    57. <version>5.0.2.RELEASEversion>
    58. dependency>
    59. <dependency>
    60. <groupId>junitgroupId>
    61. <artifactId>junitartifactId>
    62. <version>4.12version>
    63. <scope>compilescope>
    64. dependency>
    65. dependencies>
    66. <build>
    67. <plugins>
    68. <plugin>
    69. <groupId>org.apache.maven.pluginsgroupId>
    70. <artifactId>maven-compiler-pluginartifactId>
    71. <version>3.1version>
    72. <configuration>
    73. <source>1.8source>
    74. <target>1.8target>
    75. configuration>
    76. plugin>
    77. plugins>
    78. build>
    79. project>

    1.3、在xml文件中完成一系列的配置

    1. 开启组件扫描
    2. 连接数据库连接池
    3. 声明JdbcTemplate对象
    4. 创建事务管理器,并注入数据源
    5. 开启事务的注解
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:tx="http://www.springframework.org/schema/tx"
    5. xmlns:context="http://www.springframework.org/schema/context"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    8. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    9. <context:component-scan base-package="com.atguigu.spring5">context:component-scan>
    10. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    11. destroy-method="close">
    12. <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8"/>
    13. <property name="username" value="root"/>
    14. <property name="password" value="123456"/>
    15. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    16. bean>
    17. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    18. <property name="dataSource" ref="dataSource"/>
    19. bean>
    20. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    21. <property name="dataSource" ref="dataSource"/>
    22. bean>
    23. <tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>
    24. beans>

    1.4、在service类上面添加事务注解

            @Transactional注解可以加到类上面,也可以把注解添加都方法上面。

            加到类上面说明这个类的所有方法都添加事务,加到方法上面说明为当前的方法添加事务。

            service类代码(为了验证事务注解有用性,在执行过程中放置一个除数为0的操作,会抛出异常)

    1. package com.atguigu.spring5.service;
    2. import com.atguigu.spring5.dao.UserDao;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.stereotype.Service;
    5. import org.springframework.transaction.annotation.Transactional;
    6. /**
    7. * @Author 不要有情绪的 ljy
    8. * @Date 2022/9/22 13:51
    9. * @Description:
    10. */
    11. @Service
    12. @Transactional
    13. public class UserService {
    14. @Autowired
    15. private UserDao userDao;
    16. public void accountMoney() {
    17. // try {
    18. // //1.开启事务
    19. // //2.编写业务逻辑
    20. userDao.addMoney();
    21. int i = 10 / 0;
    22. userDao.reduceMoney();
    23. // //3.没有发生异常,提交事务
    24. // } catch (Exception e) {
    25. // //4.发生异常,事务回滚
    26. // e.printStackTrace();
    27. // }
    28. }
    29. }

            dao层代码

    1. package com.atguigu.spring5.dao;
    2. /**
    3. * @Author 不要有情绪的 ljy
    4. * @Date 2022/9/22 13:50
    5. * @Description:
    6. */
    7. public interface UserDao {
    8. //增加钱的功能
    9. public void addMoney();
    10. //减少钱的功能
    11. public void reduceMoney();
    12. }

            dao的实现类daoImpl代码

    1. package com.atguigu.spring5.dao;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.jdbc.core.JdbcTemplate;
    4. import org.springframework.stereotype.Repository;
    5. /**
    6. * @Author 不要有情绪的 ljy
    7. * @Date 2022/9/22 13:50
    8. * @Description:
    9. */
    10. @Repository
    11. public class UserDaoImpl implements UserDao {
    12. @Autowired
    13. private JdbcTemplate jdbcTemplate;
    14. @Override
    15. public void addMoney() {
    16. String sql = "update t_account set money = money + ? where id = ?";
    17. Object[] args = new Object[]{100,1};
    18. int update = jdbcTemplate.update(sql, args);
    19. System.out.println("钱增加成功!" + update);
    20. }
    21. @Override
    22. public void reduceMoney() {
    23. String sql = "update t_account set money = money - ? where id = ?";
    24. Object[] args = new Object[]{100, 2};
    25. int update = jdbcTemplate.update(sql, args);
    26. System.out.println("钱减少成功!" + update);
    27. }
    28. }

    1.5、编写测试类进行测试

    1. package com.atguigu.spring5.test;
    2. import com.atguigu.spring5.service.UserService;
    3. import org.junit.Test;
    4. import org.springframework.context.ApplicationContext;
    5. import org.springframework.context.support.ClassPathXmlApplicationContext;
    6. /**
    7. * @Author 不要有情绪的 ljy
    8. * @Date 2022/9/23 9:29
    9. * @Description:
    10. */
    11. public class TestAccount {
    12. @Test
    13. public void test(){
    14. ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    15. UserService userService = context.getBean("userService", UserService.class);
    16. userService.accountMoney();
    17. }
    18. }

    1.6、得到运行结果

            由于触发了异常导致,整个过程没有全部执行完,因此事务发生了回滚,数据库中的数据没有发生改变。

    2、基于完全xml配置文件的方式

    2.1、引入相关的依赖

            依赖和1.2中的依赖一致,不再写出

    2.2、在xml文件中进行配置

            配置文件相较于1.3有点不同,其主要分为以下部分:

    1. 开启组件扫描
    2. 连接数据库连接池
    3. 注册JdbcTemplate对象
    4. 创建事务管理器并注入数据源
    5. 配置通知并配置事务参数(即为哪个方法添加事务)
    6. 配置切入点和切面(即把当前的事务通知添加到切点上)
    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:tx="http://www.springframework.org/schema/tx"
    5. xmlns:aop="http://www.springframework.org/schema/aop"
    6. xmlns:context="http://www.springframework.org/schema/context"
    7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    9. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    10. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    11. <context:component-scan base-package="com.atguigu.spring5">context:component-scan>
    12. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    13. destroy-method="close">
    14. <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8"/>
    15. <property name="username" value="root"/>
    16. <property name="password" value="123456"/>
    17. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    18. bean>
    19. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    20. <property name="dataSource" ref="dataSource"/>
    21. bean>
    22. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    23. <property name="dataSource" ref="dataSource"/>
    24. bean>
    25. <tx:advice id="txadvice">
    26. <tx:attributes>
    27. <tx:method name="accountMoney" propagation="REQUIRED"/>
    28. tx:attributes>
    29. tx:advice>
    30. <aop:config>
    31. <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
    32. <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    33. aop:config>
    34. beans>

    2.3、编写业务逻辑代码

            逻辑代码和1.4章节差不多,只是要删除@Transactional注解

    1. package com.atguigu.spring5.service;
    2. import com.atguigu.spring5.dao.UserDao;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.stereotype.Service;
    5. import org.springframework.transaction.annotation.Transactional;
    6. /**
    7. * @Author 不要有情绪的 ljy
    8. * @Date 2022/9/22 13:51
    9. * @Description:
    10. */
    11. @Service
    12. //@Transactional
    13. public class UserService {
    14. @Autowired
    15. private UserDao userDao;
    16. public void accountMoney() {
    17. // try {
    18. // //1.开启事务
    19. // //2.编写业务逻辑
    20. userDao.addMoney();
    21. int i = 10 / 0;
    22. userDao.reduceMoney();
    23. // //3.没有发生异常,提交事务
    24. // } catch (Exception e) {
    25. // //4.发生异常,事务回滚
    26. // e.printStackTrace();
    27. // }
    28. }
    29. }

    2.4、测试代码的编写

    1. @Test
    2. public void test2(){
    3. ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
    4. UserService userService = context.getBean("userService", UserService.class);
    5. userService.accountMoney();
    6. }

    2.5、得到运行结果

            与1.6章节一致

    3、基于完全注解的方式

    3.1、在pom文件中添加相关依赖

            这儿不再叙说,与前面的章节一致

    3.2、编写配置类TestConfig

            此类的编写是为了代替xml配置文件,并且在该类上添加@Configuration注解,即告诉Spring容器该类是配置类。

    1. package com.atguigu.spring5.config;
    2. import com.alibaba.druid.pool.DruidDataSource;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.ComponentScan;
    5. import org.springframework.context.annotation.Configuration;
    6. import org.springframework.jdbc.core.JdbcTemplate;
    7. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    8. import org.springframework.stereotype.Component;
    9. import org.springframework.transaction.annotation.EnableTransactionManagement;
    10. /**
    11. * @Author 不要有情绪的 ljy
    12. * @Date 2022/9/29 21:53
    13. * @Description:
    14. */
    15. @Configuration //配置类
    16. @ComponentScan(basePackages = {"com.atguigu.spring5"}) //开启注解包扫描
    17. @EnableTransactionManagement //开启事务
    18. public class TestConfig {
    19. //创建数据库连接池
    20. @Bean
    21. public DruidDataSource getDruidDataSource() {
    22. DruidDataSource druidDataSource = new DruidDataSource();
    23. druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
    24. druidDataSource.setUrl("jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8");
    25. druidDataSource.setUsername("root");
    26. druidDataSource.setPassword("123456");
    27. return druidDataSource;
    28. }
    29. //创建JdbcTemplate对象
    30. @Bean
    31. public JdbcTemplate getJdbcTemplate(DruidDataSource dataSource) {
    32. JdbcTemplate jdbcTemplate = new JdbcTemplate();
    33. jdbcTemplate.setDataSource(dataSource);
    34. return jdbcTemplate;
    35. }
    36. //创建事务管理器
    37. @Bean
    38. public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource dataSource) {
    39. DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    40. dataSourceTransactionManager.setDataSource(dataSource);
    41. return dataSourceTransactionManager;
    42. }
    43. }

    3.3、编写业务逻辑代码

            与前面的一致,不再描述,但是记得添加上@Transactional注解

    3.4、编写测试类

            由于当前的配置类代替了xml配置为文件,因此测试方法在加载时候有一些变化,此时加载的应该为配置类。

    1. @Test
    2. public void test3(){
    3. ApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
    4. UserService userService = context.getBean("userService", UserService.class);
    5. userService.accountMoney();
    6. }

    3.5、得到测试运行结果

            测试得到的结果与前面一致。

    4、总结

            本博客主要讲解了三种spring管理事务的方式,每种方式原理都是一样的,要么使用注解的方式,要么配置文件的方式。整体而言使用注解方式较简单,建议在实际的开发过程中使用注解的方式,简便快速。

    学习之所以会想睡觉,是因为那是梦开始的地方。
    ଘ(੭ˊᵕˋ)੭ (开心) ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)
                                                                                                            ------不写代码不会凸的小刘

  • 相关阅读:
    java计算机毕业设计工作流流程编辑OA系统源码+mysql数据库+系统+lw文档+部署
    OpenCV:02基础知识和绘制图形
    叕跨域了...
    pandas合并操作
    应急响应靶机训练-Linux2
    MySQL事务管理
    (未学懂,待填坑)【数据结构】哈夫曼树
    Java SSL/TLS证书认证逻辑
    js 表单脚本
    idea之maven的安装与配置
  • 原文地址:https://blog.csdn.net/qq_40834643/article/details/127086106