Spring事务管理,xml和注解实现
创始人
2025-05-30 19:25:08
0

目标:熟悉事务管理的核心接口,能够说出它的3个核心接口及内容

spring-tx-5.2.8.RELEAS依赖包的3个接口

  • PlatformTransactionManager接口:可以根据属性管理事务。
  • TransactionDefinition接口:用于定义事务的属性。
  • TransactionStatus接口:用于界定事务的状态。

1.PlatformTransactionManager接口

PlatformTransactionManager接口主要用于管理事务,该接口中提供了三个管理事物的方法。

 

在实际应用中,Spring事务管理实际是由具体的持久化技术完成的,而
PlatformTransactionManager接口只提供统一的抽象方法。为了应对不同持久化技术的差异性,Spring为他们提供了具体的实现类,例如,Spring为Spring JDBC和MyBatis等依赖于DataSource的持久化技术提供了实现类DataSourceTransactionManager,如此以来,Spring JDBC或MyBatis等持久化技术的事务管理可以由DataSourceTransactionManager类实现,而且Spring 可以通过PlatformTransactionManager接口对这些实现类进行统一管理。

2.TransactionDefinition接口

TransactionDefinition接口中定义了事务描述相关的常量,其中包括了事务的隔离级别、事务的传播行为、事务的超时时间和是否为只读事务。

事务的隔离级别

 

事务的传播行为

事务的传播行为是指处于不同事务中的方法在相互调用时,方法执行期间,事务的维护情况。例如,当一个事务的方法B调用另一个事务的方法A时,可以规定A方法继续在B方法所属的现有事务中运行,也可以规定A方法开启一个新事务,在新事务中运行,B方法所属的现有事务先挂起,等A方法的新事务执行完毕后再恢复。

TransactionDefinition接口中定义的7种事务传播行为

事务的超时时间

事务的超时时间是指事务执行的时间界限,超过这个时间界限,事务将会回滚。TransactionDefinition接口提供了TIMEOUT_DEFAULT常量定义事务的超时时间。 

是否为只读事务

当事务为只读时,该事务不修改任何数据,只读事务有助于提升性能,如果在只读事务中修改数据,会引发异常。TransactionDefinition接口中除了提供事务的隔离级别、事务的传播行为、事务的超时时间和是否为只读事务的常量外,还提供了一系列方法来获取事务的属性。

TransactionDefinition接口常用方法

3.TransactionStatus接口 

TransactionStatus接口主要用于界定事务的状态,通常情况下,编程式事务中使用该接口较多。TransactionStatus接口提供了一系列返回事务状态信息的方法,具体如下。

熟悉事务管理的方式,能够说出Spring事务管理的两种方式分别是什么 

Spring中的事务管理分为两种方式,一种是传统的编程式事务管理,另一种是声明式事务管理。

  • 编程式事务管理:通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚。
  • 声明式事务管理:通过AOP技术实现的事务管理,其主要思想是将事务管理作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”代码植入到业务目标类中。

编写式事务管理有点落后,一般使用第二种,声明式事务管理

实现XML方式的声明式事务

没有配置事务具体实现代码:

这是一开始表中的数据:

 现在模拟zhangsan给lisi转账100元

pom.xml


4.0.0org.example_202303191.0-SNAPSHOT88UTF-8org.springframeworkspring-context5.2.3.RELEASEorg.springframeworkspring-beans5.2.3.RELEASEmysqlmysql-connector-java5.1.47org.springframeworkspring-jdbc5.3.6org.springframeworkspring-tx5.3.6org.springframeworkspring-aspects4.2.4.RELEASE

 AccountDaoImpl:

package cn.hdc.dao.impl;import cn.hdc.dao.AccountDao;
import cn.hdc.model.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;import java.util.List;public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic Integer addAccount(Account account) {String sql = "insert into account(username,balance) values(?,?)";Object[] params = new Object[]{account.getUsername(), account.getBalance()};jdbcTemplate.update(sql, params);return jdbcTemplate.update(sql, params);}@Overridepublic Integer deleteAccount(Integer id) {String sql = "delete from account where id = ?";return jdbcTemplate.update(sql, id);}@Overridepublic Integer updateAccount(Account account) {String sql = "update account set username=?,balance=? where id=?";Object[] params = new Object[]{account.getUsername(), account.getBalance(), account.getId()};return jdbcTemplate.update(sql, params);}@Overridepublic Account findAccountById(Integer id) {String sql = "select * from account where id = ?";RowMapper accountRowMapper = new BeanPropertyRowMapper<>(Account.class);Account account = jdbcTemplate.queryForObject(sql, accountRowMapper, id);return jdbcTemplate.queryForObject(sql, accountRowMapper, id);}@Overridepublic List findAll() {String sql = "select * from account";RowMapper accountRowMapper = new BeanPropertyRowMapper<>(Account.class);List list = jdbcTemplate.query(sql, accountRowMapper);return list;}//模拟转账操作@Overridepublic void transfer(String outUser, String inUser, Double money) {//收款jdbcTemplate.update("update account set balance = balance + ? where username = ?", money, inUser);//模拟异常int i = 10 / 0;//付款jdbcTemplate.update("update account set balance = balance - ? where username = ?", money, outUser);}
}

AccountDao接口:

package cn.hdc.dao;import cn.hdc.model.Account;import java.util.List;public interface AccountDao {public Integer addAccount(Account account);public Integer deleteAccount(Integer id);public Integer updateAccount(Account account);public Account findAccountById(Integer id);public List findAll();public void transfer(String outUser, String inUser, Double money);
}

Account实体类:

package cn.hdc.model;public class Account {private Integer id;private String username;private Double balance;@Overridepublic String toString() {return "Account{" +"id=" + id +", username='" + username + '\'' +", balance=" + balance +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}
}

测试类:

import cn.hdc.dao.AccountDao;
import cn.hdc.dao.impl.AccountDaoImpl;
import cn.hdc.model.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;public class APP {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");AccountDao accountDao = (AccountDao) context.getBean("accountDao");accountDao.transfer("zhangsan", "lisi", 100.0);//        List list = accountDao.findAll();
//        list.forEach(account -> {
//            System.out.println(account);
//        });//        Account account = accountDao.findAccountById(1);
//        System.out.println(account);//        Integer ret = accountDao.deleteAccount(2);
//        if (ret > 0) {
//            System.out.println("删除成功!");
//        } else {
//            System.out.println("删除失败!");
//        }
//        Account account1 = new Account();
//        account1.setId(2);
//        account1.setUsername("zhangsan");
//        account1.setBalance(5000.02153);
//        Integer ret = accountDao.updateAccount(account1);
//        if (ret > 0) {
//            System.out.println("修改成功!");
//        } else {
//            System.out.println("修改失败!");
//        }//        Account account = new Account();
//        account.setUsername("tom");
//        account.setBalance(1000.011);
//        Integer ret = accountDao.addAccount(account);
//        if (ret > 0) {
//            System.out.println("插入成功!");
//        } else {
//            System.out.println("插入失败!");
//        }//        jdbcTemplate.execute("create table account" +
//                "(" +
//                "    id int primary key auto_increment," +
//                "    username varchar(50)," +
//                "    balance double" +
//                ");");
//        System.out.println("account表创建成功!");//        UserDaoImpl userDao = (UserDaoImpl) context.getBean("userDao");//        System.out.println(userDao.getJdbcTemplate());}
}

运行结果:

看一下表数据:

 

 张三的钱没扣!

接下来我们使用事务

具体实现代码:

现在还原一下表

pom.xml


4.0.0org.example_202303191.0-SNAPSHOT88UTF-8org.springframeworkspring-context5.2.3.RELEASEorg.springframeworkspring-beans5.2.3.RELEASEmysqlmysql-connector-java5.1.47org.springframeworkspring-jdbc5.3.6org.springframeworkspring-tx5.3.6org.springframeworkspring-aspects4.2.4.RELEASEorg.aspectjaspectjweaver1.9.6aopallianceaopalliance1.0

 

AccountDao接口:

package cn.hdc.dao;import cn.hdc.model.Account;import java.util.List;public interface AccountDao {public Integer addAccount(Account account);public Integer deleteAccount(Integer id);public Integer updateAccount(Account account);public Account findAccountById(Integer id);public List findAll();public void transfer(String outUser, String inUser, Double money);
}

AccountDaoImpl

package cn.hdc.dao.impl;import cn.hdc.dao.AccountDao;
import cn.hdc.model.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;import java.util.List;public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic Integer addAccount(Account account) {String sql = "insert into account(username,balance) values(?,?)";Object[] params = new Object[]{account.getUsername(), account.getBalance()};jdbcTemplate.update(sql, params);return jdbcTemplate.update(sql, params);}@Overridepublic Integer deleteAccount(Integer id) {String sql = "delete from account where id = ?";return jdbcTemplate.update(sql, id);}@Overridepublic Integer updateAccount(Account account) {String sql = "update account set username=?,balance=? where id=?";Object[] params = new Object[]{account.getUsername(), account.getBalance(), account.getId()};return jdbcTemplate.update(sql, params);}@Overridepublic Account findAccountById(Integer id) {String sql = "select * from account where id = ?";RowMapper accountRowMapper = new BeanPropertyRowMapper<>(Account.class);Account account = jdbcTemplate.queryForObject(sql, accountRowMapper, id);return jdbcTemplate.queryForObject(sql, accountRowMapper, id);}@Overridepublic List findAll() {String sql = "select * from account";RowMapper accountRowMapper = new BeanPropertyRowMapper<>(Account.class);List list = jdbcTemplate.query(sql, accountRowMapper);return list;}//模拟转账操作@Overridepublic void transfer(String outUser, String inUser, Double money) {//收款jdbcTemplate.update("update account set balance = balance + ? where username = ?", money, inUser);//模拟异常int i = 10 / 0;//付款jdbcTemplate.update("update account set balance = balance - ? where username = ?", money, outUser);}
}

Account实体类:

package cn.hdc.model;public class Account {private Integer id;private String username;private Double balance;@Overridepublic String toString() {return "Account{" +"id=" + id +", username='" + username + '\'' +", balance=" + balance +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}
}

applicationContext.xml



 

测试类:

import cn.hdc.dao.AccountDao;
import cn.hdc.dao.impl.AccountDaoImpl;
import cn.hdc.model.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;import java.util.List;public class APP {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");AccountDao accountDao = (AccountDao) context.getBean("accountDao");accountDao.transfer("zhangsan", "lisi", 100.0);//        List list = accountDao.findAll();
//        list.forEach(account -> {
//            System.out.println(account);
//        });//        Account account = accountDao.findAccountById(1);
//        System.out.println(account);//        Integer ret = accountDao.deleteAccount(2);
//        if (ret > 0) {
//            System.out.println("删除成功!");
//        } else {
//            System.out.println("删除失败!");
//        }
//        Account account1 = new Account();
//        account1.setId(2);
//        account1.setUsername("zhangsan");
//        account1.setBalance(5000.02153);
//        Integer ret = accountDao.updateAccount(account1);
//        if (ret > 0) {
//            System.out.println("修改成功!");
//        } else {
//            System.out.println("修改失败!");
//        }//        Account account = new Account();
//        account.setUsername("tom");
//        account.setBalance(1000.011);
//        Integer ret = accountDao.addAccount(account);
//        if (ret > 0) {
//            System.out.println("插入成功!");
//        } else {
//            System.out.println("插入失败!");
//        }//        jdbcTemplate.execute("create table account" +
//                "(" +
//                "    id int primary key auto_increment," +
//                "    username varchar(50)," +
//                "    balance double" +
//                ");");
//        System.out.println("account表创建成功!");//        UserDaoImpl userDao = (UserDaoImpl) context.getBean("userDao");//        System.out.println(userDao.getJdbcTemplate());}
}

运行结果:

 

表中数据没有变化,事务发生了回滚。 

基于注解方式的声明式事务

@Transactional的属性

 

AccountDaoImpl在原来的基础上加上注解

 

applicationContext.xml

 运行结果:

 

表中数据没有发生改变,事务生效

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...