Spring-声明式事务实例(有详细注释)

前提知识

Spring-IOC容器注解方式使用icon-default.png?t=N7T8https://blog.csdn.net/m0_61160520/article/details/136784799?spm=1001.2014.3001.5501
切点表达式icon-default.png?t=N7T8https://blog.csdn.net/m0_61160520/article/details/136782885?spm=1001.2014.3001.5501

案例 

1.创建项目

2.导入依赖

<dependency>                                       <groupId>mysql</groupId>                       <artifactId>mysql-connector-java</artifactId>  <version>8.0.25</version>                      
</dependency>                                      
<dependency>                                       <groupId>com.alibaba</groupId>                 <artifactId>druid</artifactId>                 <version>1.2.8</version>                       
</dependency>                                      
<!-- spring-jdbc -->                               
<dependency>                                       <groupId>org.springframework</groupId>         <artifactId>spring-jdbc</artifactId>           <version>6.0.6</version>                       
</dependency>                                      <dependency>                                       <groupId>org.springframework</groupId>         <artifactId>spring-tx</artifactId>             <version>6.0.6</version>                       
</dependency>                                      

3.数据库准备 

-- ----------------------------
-- Table structure for students
-- ----------------------------
DROP TABLE IF EXISTS `students`;
CREATE TABLE `students`  (`id` int NOT NULL,`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`gender` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`age` int NULL DEFAULT NULL,`class` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of students
-- ----------------------------
INSERT INTO `students` VALUES (1, '喜羊羊', '男', 18, '高中一班');
INSERT INTO `students` VALUES (2, '美羊羊', '女', 19, '高中二班');
INSERT INTO `students` VALUES (3, '懒羊羊', '男', 18, '高中一班');
INSERT INTO `students` VALUES (4, '沸羊羊', '男', 18, '高中三班');
INSERT INTO `students` VALUES (5, '暖羊羊', '女', 19, '高中二班');
INSERT INTO `students` VALUES (6, '软绵绵', '男', 60, '高中一班');
INSERT INTO `students` VALUES (7, '灰太狼', '男', 30, '高中三班');
INSERT INTO `students` VALUES (8, '红太狼', '女', 30, '高中二班');SET FOREIGN_KEY_CHECKS = 1;

4.外部配置文件jdbc.properties

cx.url=jdbc:mysql://localhost:3306/studb
cx.driver=com.mysql.cj.jdbc.Driver
cx.username=root
cx.password=123456

5.编写配置类

@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:jdbc.properties")
//@EnableAspectJAutoProxy //开启aspectj注解的支持
@EnableTransactionManagement //开启事务注解的支持
public class JavaConfig {/*从配置文件中读取数据库连接的相关信息。*/@Value("${cx.driver}")private String driver;@Value("${cx.url}")private String url;@Value("${cx.username}")private String username;@Value("${cx.password}")private String password;//druid连接池,使用 Druid 连接池来管理数据库连接。@Beanpublic DataSource dataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}//创建一个 JdbcTemplate bean,将上面创建的数据源对象注入其中,用于执行数据库查询和更新操作。@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}//创建一个用于管理事务的 TransactionManager bean,将数据源对象注入其中,以便在事务中控制数据库的操作。@Beanpublic TransactionManager transactionManager(DataSource dataSource){//内部要进行事务的操作,基于的连接池DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();//需要连接池对象dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}

6.简单准备一个dao/service层

dao

@Repository
public class StudentDao {//声明一个 JdbcTemplate 对象作为成员变量来执行数据库操作。private JdbcTemplate jdbcTemplate;@Autowiredpublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}public void updateNameById(String name, Integer id){String sql = "update students set name = ? where id = ? ;";int rows = jdbcTemplate.update(sql, name, id);}public void updateAgeById(Integer age,Integer id){String sql = "update students set age = ? where id = ? ;";jdbcTemplate.update(sql,age,id);}
}

service(重要内容)

添加事务:

 @Transactional
      位置: 方法 | 类上
      方法: 当前方法有事务
      类上: 类下的所有方法都有事务

 1.只读模式

         只读模式可以提升查询事务的效率! 推荐事务中只有查询代码,使用只读模式!
         默认: boolean readOnly() default false;
         解释: 一般情况下,都是通过类添加注解添加事务!
         类下的所有方法都有事务!
         查询方法可以通过再次添加注解,设置为只读模式,提高效率!

 2.超时时间

         默认: 永远不超时  -1
         设置 timeout = 时间 秒数  超过时间,就会回滚事务和释放异常!         TransactionTimedOutException
        如果类上设置事务属性,方法也设置了事务注解! 方法会不会生效??
        不会生效: 方法上的注解覆盖了类上的注解!

 3.指定异常回滚和指定异常不回滚:

        默认情况下,指定发生运行时异常事务才会回滚!
        我们可以指定Exception异常来控制所有异常都回滚!
        rollbackFor = Exception.class
        noRollbackFor = 回滚异常范围内,控制某个异常不回滚!

 4.隔离级别设置

        推荐设置第二个隔离级别!
        isolation = Isolation.READ_COMMITTED

@Transactional(timeout = 3)//超时时间
@Service
public class StudentService {private StudentDao studentDao;@Autowiredpublic void setStudentDao(StudentDao studentDao) {this.studentDao = studentDao;}@Transactional(readOnly = false ,rollbackFor = Exception.class , noRollbackFor = FileNotFoundException.class,isolation = Isolation.READ_COMMITTED)public void changeInfo() throws FileNotFoundException {studentDao.updateAgeById(99, 1);new FileInputStream("xxxx");studentDao.updateNameById("test3", 1);}@Transactional(readOnly = true)public void changeInfo2() {//查询 没有必要添加事务!//获取学生信息 查询数据库 不修改}/*** 声明两个独立修改数据库的事务业务方法* propagation = Propagation.REQUIRED 父方法有事务,我们就加入到父方法的事务!*              最终是同一个事务! 推荐使用默认值!!** propagation = Propagation.REQUIRES_NEW*               不管父方法是否有事务,我都是独立的事务!*               两个事务或者三个事务!*/@Transactional(propagation = Propagation.REQUIRED)public void changeAge(){studentDao.updateAgeById(8,1);}@Transactional(propagation = Propagation.REQUIRED)public void changeName(){studentDao.updateNameById("二狗子",1);int i = 1/0; //报错}
}

封装类TopService

@Service
public class TopService {@Autowiredprivate StudentService studentService;@Transactionalpublic void  topService(){studentService.changeAge();studentService.changeName();}
}

为什么要这个封装类呢?移步以下博客

主要涉及了事务的控制与管理 icon-default.png?t=N7T8https://blog.csdn.net/m0_61160520/article/details/136966627?spm=1001.2014.3001.5501

7.测试

@SpringJUnitConfig(JavaConfig.class)
public class TxTest {@Autowiredprivate TopService topService;@Autowiredprivate StudentService studentService;@Testpublic void  testTx() throws FileNotFoundException {topService.topService();}
}

结果:数据库中age被修改,因为使用的Propagation.REQUIRES_NEW,表示每个方法都会创建一个新的事务,独立于外部事务,即使其他方法报错,正常方法会被执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/767192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react native 总结

react app.js 相当与vue app.vue import React from react; import ./App.css; import ReactRoute from ./router import {HashRouter as Router,Link} from react-router-dom class App extends React.Component {constructor(props){super(props)}render(){return ( <…

记使用sjson的一次小事故

1. 前言 之前在设计一个兼容函数的时候&#xff0c;使用了sjson动态设入参数&#xff0c;从而实现一些参数的兼容。大致的逻辑如下所示&#xff1a; // 有一堆不规则的json数据 {"a":"aaa","b":"bbb","any_key1":{"k…

Cache缓存:HTTP缓存策略解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

蓝桥杯每日一题(拓扑排序)

//3696构造有向无环图 有向无环图才有拓扑排序&#xff0c;有环的话不能进行拓扑&#xff0c;因为会导致环中一个结点&#xff08;环的入口位置&#xff09;其入度永远无法变成0。 先判断图是否可拓扑序&#xff0c;如果本来就不能就直接No&#xff0c;可以的话。可以按照拓扑…

为什么元素显示的样式跟我设置的不一样?CSS优先级详解

一、什么是CSS中的选择器优先级&#xff1f; 在CSS中&#xff0c;选择器优先级是指确定应用于元素的最相关CSS声明的算法。这个优先级决定了哪个样式规则将被应用到元素上。根据选择器的类型和特定性&#xff0c;CSS规定了不同的优先级&#xff0c;例如ID选择器比类选择器具有更…

select , poll, epoll思维导图

目录 1. 总的框架结构 2. select 3. poll 4. epoll 1. 总的框架结构 2. select

SpringCloud-Gateway服务网关

一、网关介绍 1. 为什么需要网关 Gateway网关是我们服务的守门神&#xff0c;所有微服务的统一入口。 网关的核心功能特性&#xff1a; 请求路由 权限控制 限流 架构图&#xff1a; 权限控制&#xff1a;网关作为微服务入口&#xff0c;需要校验用户是是否有请求资格&am…

使用阿里云服务器搭建网站教程,超简单10分钟网站上线

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

Python之functools模块之lru_cache

Python之functools模块之lru_cache lru_cache functools.lru_cache(maxsize128, typedFalse)lru即Least-recently-used&#xff0c;最近最少使用。cache缓存 如果maxsize设置为None&#xff0c;则禁用LRU功能&#xff0c;并且缓存可以无限制增长。当maxsize是二的幂时&#x…

基于python+vue分类信息服务平台移动端的设计与实现flask-django-php-nodejs

分类信息服务平台是在Android操作系统下的应用平台。为防止出现兼容性及稳定性问题&#xff0c;框架选择的是django&#xff0c;Android与后台服务端之间的数据存储主要通过MySQL。用户在使用应用时产生的数据通过 python等语言传递给数据库。通过此方式促进分类信息服务平台信…

蓝桥杯单片机快速开发笔记——PCF8591的DAC模拟电压输出

一、原理分析 PCF8591电压信号探测器&#xff1a;http://t.csdnimg.cn/R38tC IIC原理&#xff1a;http://t.csdnimg.cn/v4dSv IIC指令&#xff1a;http://t.csdnimg.cn/RY6yi HC573/HC138&#xff1a;http://t.csdnimg.cn/W0a0U 数码管&#xff1a;http://t.csdnimg.cn/kfm9Y 独…

鸿蒙OpenHarmony开发实战:【MiniCanvas】

介绍 基于OpenHarmony的Cavas组件封装了一版极简操作的MiniCanvas&#xff0c;屏蔽了原有Canvas内部复杂的调用流程&#xff0c;支持一个API就可以实现相应的绘制能力&#xff0c;该库还在继续完善中&#xff0c;也欢迎PR。 使用说明 添加MiniCanvas依赖 在项目entry目录执行…

小桥的神秘礼物盒

0小桥的神秘礼物盒 - 蓝桥云课 (lanqiao.cn) 问题描述 在一个阳光明媚的早晨&#xff0c;小桥收到了一份神秘的礼物--一只魔法盒子。这个盒子有四个按钮&#xff0c;每个按钮都有特殊的功能: 按钮 A:“添加”&#xff0c;将一个神秘物品 (每个物品都有一个独特的编号)放入盒子中…

3693. 括号匹配 南京理工大学考研上机真题 栈的使用 注意检测栈是否为空

苗苗今天刚刚学会使用括号&#xff0c;不过他分不清小括号&#xff0c;中括号&#xff0c;大括号和尖括号&#xff0c;不知道怎么使用这些括号&#xff0c;请帮助他判断括号使用是否正确。 注意&#xff1a;不需要区分括号的优先级。 输入格式 共一行&#xff0c;包含一个由…

Docker学习笔记 - 常用命令

目录 基本概念常用命令使用docker compose启动脚本创建自己的image Docker命令文档 1. 下载一个image 从hub.docker.com下载一个image。 docker pull [image name]下载时指定image的tag。 docker pull [image name]:<tag>举例&#xff0c;下载postgre的tag为alpine…

【WEEK4】学习目标及总结【SpringMVC】【中文版】

学习目标&#xff1a; 三周四周 完成SpringMVC入门——第四周 这周一定 学习内容&#xff1a; 参考视频教程【狂神说Java】SpringMVC最新教程IDEA版通俗易懂整合SSM框架 Spring SpringMVC环境进行增删查改操作 AJAX 学习时间及产出&#xff1a; 第四周 MON~FRI 2024.3.18【…

CPP容器vector和list,priority_queue定义比较器

#include <iostream> #include <bits/stdc.h> using namespace std; struct VecCmp{bool operator()(int& a,int& b){return a>b;/*** 对于vector和list容器&#xff0c;这里写了&#xff1e;就是从大到小* 对于priority_queue容器&#xff0c;这里写…

配置java8和java11以及输入version命令没反应问题

电脑重置重新安装java8和java11记录一下供自己观看 安装过程掠过我自己能看懂就行 需要记录一下 因为JDK11以后Oracle把JRE集成到了JDK中&#xff0c;在安装JDK11及更高版本的JDK时&#xff0c;默认是不会自动安装JRE的。在jdk11的安装目录下打开命令行窗口或者shift鼠标右键…

婚恋小程序开发的资质需要哪些?维护成本高吗?

随着互联网的高速发展&#xff0c;人们的生活方式也在发生着翻天覆地的变化。在这个变化中&#xff0c;婚恋市场也逐渐走向了线上&#xff0c;婚恋小程序应运而生。那么&#xff0c;开发一款婚恋小程序需要哪些资质呢&#xff1f;维护成本又高不高呢&#xff1f;本文将从这两个…

[小程序开发] 自定义导航栏

在app.json或者page.json中&#xff0c;配置navigationStyle属性为custom&#xff0c;即可自定义导航栏。在设置以后&#xff0c;就会移除默认的导航栏&#xff0c;只保留右上角胶囊按钮。 "navigationStyle":"custom"