示例:Spring JDBC 声明式事务(xml配置形式)

声明式事务是指在不修改源代码的情况下通过配置applicationContext.xml自动实现事务控制,其本质是AOP环绕通知。它的触发时机为:1、当目标方法执行成功时自动提交事务,2、当目标方法抛出运行时异常时,自动事务回滚


核心步骤示例(基于 XML 配置)

1. 添加依赖

因为是基于AOP,所以必须引入aop和aspectjweaver:

	 <!-- Spring 上下文支持 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.30</version></dependency><!-- Spring JDBC 核心依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.30</version></dependency><!-- 数据库驱动(以 MySQL 为例) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- JUnit 4 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!-- Spring Test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.30</version><scope>test</scope></dependency><!-- Spring AOP --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.30</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version></dependency><!--logback日志组件,spring框架默认集成--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.3.12</version></dependency>

2.applicationContext.xml配置

主要步骤如下:
1、配置TransactionManager事务管理器
2、配置事务通知与事务属性
3、为事务通知绑定ponitCut切点
例如:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:contex="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd
"><!-- 加载属性文件 --><contex:property-placeholder location="application.properties"/><!-- 配置数据源(使用DriverManagerDataSource,适用于简单场景) --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--jdbcTemplate配置--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean>   <!--1、配置事务管理器,用于事务创建、提交、回滚--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--2、事务通知配置,决定哪些方法使用事务,哪些方法不使用事务--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--当目标方法符合正则表达式“batch*”时,启用声明式事务--><tx:method name="batch*" propagation="REQUIRED"/><!--当目标方法符合正则表达式“find*”时,不需要启用声明式事务--><tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true" /><!--当目标方法符合正则表达式“get*”时,不需要启用声明式事务--><tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true" /><!--其他目标方法,根据项目需要设置启用声明式事务或不启用事务--><tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" /></tx:attributes></tx:advice><!--3、定义声明式事务的作用范围--><aop:config><aop:pointcut id="transactionPointcut" expression="execution(* com.hirain.service.*Service.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/></aop:config><bean id="employeeDao" class="com.hirain.dao.EmployeeDao"><property name="jdbcTemplate" ref="jdbcTemplate"/></bean><bean id="employeeService" class="com.hirain.service.EmployeeService"><property name="employeeDao" ref="employeeDao"/><property name="transactionManager" ref="transactionManager"/></bean>
</beans>

3. Service层代码
package com.hirain.service;import com.hirain.dao.EmployeeDao;
import com.hirain.entity.Employee;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;public class EmployeeService {private EmployeeDao employeeDao;private DataSourceTransactionManager transactionManager;public void batchInsert() {for (int i = 0; i < 10; i++) {if (i==3){throw new RuntimeException("生成员工数据异常");}Employee employee = new Employee();employee.setEmployeeId(80+i);employee.setName("新员工"+i);employee.setDepartmentId(2l);employee.setTitle("客服");employee.setLevel(1);employeeDao.insert(employee);}}
//...getter and setter
}

4. DAO 层代码
package com.hirain.dao;import com.hirain.entity.Employee;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;public class EmployeeDao {private JdbcTemplate jdbcTemplate;public Employee findById(long id){String sql = "select * from adm_employee where employee_id=?";Employee employee = jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<Employee>(Employee.class));return employee;}public int insert(Employee employee){String sql="insert into adm_employee (employee_id,name,department_id,title,level) values(?,?,?,?,?)";int rows = jdbcTemplate.update(sql,new Object[]{employee.getEmployeeId(),employee.getName(),employee.getDepartmentId(),employee.getTitle(),employee.getLevel()});return rows;}public int update(Employee employee){String sql="UPDATE adm_employee SET name=?,department_id=?,title=?,level=? WHERE employee_id=?";int rows = jdbcTemplate.update(sql,new Object[]{employee.getName(),employee.getDepartmentId(),employee.getTitle(),employee.getLevel(),employee.getEmployeeId()});return rows;}public int delete(long id){String sql="delete from adm_employee where employee_id=?";int rows = jdbcTemplate.update(sql,new Object[]{id});return rows;}public EmployeeDao() {}//...getter and setter
}

5.测试代码
import com.hirain.dao.EmployeeDao;
import com.hirain.entity.Employee;
import com.hirain.service.EmployeeService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class) // 使用 Spring 的测试运行器
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) // 加载 Spring 配置文件
public class JDBCTemplateTest { @Autowiredprivate EmployeeService employeeService; @Testpublic void testBantchInsert() {employeeService.batchInsert();}}

关键配置说明

** @Transactional 注解属性**
  • 传播行为propagation(默认 REQUIRED)。
  • 隔离级别isolation(默认数据库级别)。
  • 超时时间timeout(秒)。
  • 只读事务readOnly(优化查询)。
  • 回滚规则rollbackFor(指定触发回滚的异常类型)。

声明式事务 vs 编程式事务

特性声明式事务(@Transactional)编程式事务(TransactionTemplate)
代码侵入性低(注解声明)高(手动控制事务边界)
灵活性低(固定事务属性)高(动态调整事务属性)
适用场景大多数简单到中等复杂度场景需要动态事务控制的复杂场景

注意事项

  1. 异常类型:默认仅 RuntimeExceptionError 触发回滚,需通过 rollbackFor 指定其他异常。
  2. 自调用失效:在同一个类中通过 this.xxxMethod() 调用事务方法,事务可能失效(需通过代理对象调用)。
  3. 数据库支持:事务需要数据库引擎支持(如 MySQL 的 InnoDB)。

通过声明式事务,开发者可以专注于业务逻辑,无需手动管理事务边界,代码更简洁且易于维护。

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

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

相关文章

在vmware中ubuntu系统因为安装了docker查不到ip地址

问题截图&#xff1a; 根据提供的截图信息&#xff0c;可以明确看到ens33网卡处于**物理连接断开&#xff08;NO-CARRIER&#xff09;且接口关闭&#xff08;DOWN&#xff09;**的状态&#xff0c;这是导致无法获取IP地址的直接原因。以下是针对VMware虚拟机的具体解决方案&am…

51c大模型~合集121

我自己的原文哦~ https://blog.51cto.com/whaosoft/13869815 #大模型何以擅长小样本学习&#xff1f; 这项研究给出详细分析 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;在人工智能领域取得了突破性进展&#xff0c;成为推动自然语言处理技术发展与通用人…

Babylon.js 材质统一转换指南:将 AssetContainer 中的所有材质转换为 PBRMetallicRoughnessMaterial

在现代 3D 开发中&#xff0c;基于物理的渲染(PBR)已成为行业标准。本文将详细介绍如何在 Babylon.js 中将 AssetContainer 加载的各种材质统一转换为 PBRMetallicRoughnessMaterial&#xff0c;实现项目材质的标准化。 为什么需要材质转换&#xff1f; PBRMetallicRoughness…

Go slice切片使用教程,一次通关!

简介 Go 中的 切片&#xff08;slice&#xff09; 是 Go 最强大、最常用的数据结构之一。它是对数组的轻量封装&#xff0c;比数组更灵活&#xff0c;几乎所有的集合处理都用切片来完成。 什么是切片&#xff08;slice&#xff09; 切片是一个拥有 长度&#xff08;len&…

nodejs的包管理工具介绍,npm的介绍和安装,npm的初始化包 ,搜索包,下载安装包

nodejs的包管理工具介绍&#xff0c;npm的介绍和安装&#xff0c;npm的初始化包 &#xff0c;搜索包&#xff0c;下载安装包 &#x1f9f0; 一、Node.js 的包管理工具有哪些&#xff1f; 工具简介是否默认特点npmNode.js 官方的包管理工具&#xff08;Node Package Manager&am…

FPGA设计 时空变换

1、时空变换基本概念 1.1、时空概念简介 时钟速度决定完成任务需要的时间&#xff0c;规模的大小决定完成任务所需要的空间&#xff08;资源&#xff09;&#xff0c;因此速度和规模就是FPGA中时间和空间的体现。 如果要提高FPGA的时钟&#xff0c;每个clk内组合逻辑所能做的事…

增加首屏图片

增加首屏图片&#xff08;bg.jpg&#xff09; web-mobile类型打包 //index.html脚本 <div id"myDiv_1111"style"background: url(./bg.jpg) 50% 50%/ 100% auto no-repeat ; width:100%;height:100%;position:absolute;"></div> //游戏内脚本…

贪心算法~~

目录 一、理论基础 二、题目练习 &#xff08;1&#xff09;455. 分发饼干 &#xff08;2&#xff09;53. 最大子数组和 - 力扣 &#xff08;3&#xff09;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; &#xff08;4&#xff09;860. 柠檬水找零…

形象解释 HTTP 的四种常见请求方式及其中的区别联系

HTTP 的常见请求方式常见的有四种&#xff1a;GET、POST、PUT、DELETE&#xff0c;它们各自的功能不一样。 &#x1f35c; 场景比喻&#xff1a;HTTP 请求像“去餐厅点菜” 请求方式行为餐厅比喻说明GET获取数据看菜单/问服务员&#xff1a;你们有什么菜&#xff1f;不带食材、…

string的基本使用

string的模拟实现 string的基本用法string的遍历&#xff08;三种方式&#xff09;&#xff1a;关于auto&#xff08;自动推导&#xff09;:范围for: 迭代器普通迭代器(可读可改&#xff09;const迭代器&#xff08;可读不可改&#xff09; string细小知识点string的常见接口引…

kubernetes》》k8s》》证书有效期

cd /etc/kubernetes/pki openssl x509 -in apiserver.crt -text -noount通常&#xff0c;Kubernetes的证书是由kubeadm生成的&#xff0c;所以可能需要修改kubeadm的源码或者配置 登录Master节点 》》》默认延续1年 # 查看证书 检查证书有效期 # 该命令显示 /etc/kubernetes…

LangChain LCEL表达式语言简介

LangChain表达式语言&#xff08;LCEL&#xff09;是专为构建AI应用链设计的声明式编程框架&#xff0c;通过管道符|实现组件无缝衔接&#xff0c;支持流式处理、异步调用等生产级特性。其核心优势在于零代码改动实现原型到生产的过渡&#xff0c;同时保持代码简洁性和可维护性…

【计算机视觉】CV实践项目- 基于PaddleSeg的遥感建筑变化检测全解析:从U-Net 3+原理到工程实践

基于PaddleSeg的遥感建筑变化检测全解析&#xff1a;从U-Net 3原理到工程实践 技术背景与项目意义传统方法的局限性深度学习的优势 核心技术与算法原理U-Net 3架构创新全尺度跳跃连接深度监督机制 变化检测技术路线 实战指南&#xff1a;从环境搭建到模型部署环境配置数据准备与…

万字长文 | Apache SeaTunnel 分离集群模式部署 K8s 集群实践

文章作者&#xff1a;雷宝鑫 整理排版&#xff1a;白鲸开源 曾辉 Apache SeaTunnel官网链接: https://seatunnel.apache.org/ Apache SeaTunnel(以下简称SeaTunnel&#xff09;是一款新一代高性能、分布式的数据集成同步工具&#xff0c;正受到业界广泛关注和应用。SeaTunnel支…

深入解析YOLO v1:实时目标检测的开山之作

目录 YOLO v1 算法详解​ ​1. 核心思想​ ​2. 算法优势​ ​3. 网络结构&#xff08;Unified Detection&#xff09;​​ ​4. 关键创新​ ​5. 结构示意图&#xff08;Fig1&#xff09;​ Confidence Score 的计算​ 类别概率与 Bounding Box 的关系​ 后处理&…

信令与流程分析

WebRTC是h5支持的重要特征之一&#xff0c;有了它&#xff0c;不再需要借助音视频相关的客户端&#xff0c;直接通过浏览器的Web页面就可以实现音视频聊天功能。 WebRTC项目是开源的&#xff0c;我们可以借助WebRTC&#xff0c;构建自己的音视频聊缇娜功能。无论是前端JS的Web…

BIOS主板(非UEFI)安装fedora42的方法

BIOS主板(非UEFI)安装fedora42的方法 现实困难&#xff1a;将Fedora-Workstation-Live-42-1.1.x86_64.iso写入U盘制作成可启动U盘启动fedora42&#xff0c;按照向导将fedora42安装到真机的sda7分区中得到报错如下内容&#xff1a; /boot/efi 必需的 /boot/efi必须位于格式化为e…

安卓 Compose 相对传统 View 的优势

安卓 Compose 相对传统 View 的优势 文章目录 安卓 Compose 相对传统 View 的优势1. 引言2. 核心概念&#xff1a;Compose的革新性设计2.1 Jetpack Compose2.2 传统安卓View系统 3. 开发体验&#xff1a;Compose大幅提升效率3.1 使用Jetpack Compose构建UI3.2 使用传统View系统…

SIEMENS PLC 程序 GRAPH 程序解读 车型入库

1、程序载图1 2、程序截图2 3、程序解释 这是一个基于西门子 GRAPH 编程的车型 1 入库顺序控制流程图&#xff0c;通过状态机结构&#xff08;状态框 S 与转移条件 T&#xff09;描述完整工作流程&#xff0c;具体如下&#xff1a; 整体流程概述 初始化&#xff1a;从 S1&am…

VuePress可以做什么?

VuePress 可以做什么 VuePress 是一个基于 Vue.js 的静态站点生成器,专注于文档和内容展示。它结合了 Markdown 的简洁性和 Vue 的灵活性,适合多种场景的开发需求。以下是 VuePress 的主要用途和功能: 1. 技术文档网站 VuePress 最初是为编写 Vue.js 官方文档而设计的,因…