【Spring Framework】Spring 事务使用的完整示例

为了详细展示 Spring 事务的使用,我将提供一个完整的示例,包括配置、代码和说明。这将涵盖以下几个方面:

  1. 数据库配置:包括数据源和事务管理器的配置。
  2. 实体类:用于数据库操作的数据模型。
  3. DAO 层:数据访问对象,用于执行数据库操作。
  4. 服务层:业务逻辑层,包含事务管理的业务方法。
  5. 配置:包括 Java 配置和 XML 配置示例。
  6. 测试:如何测试事务管理的功能。

示例项目结构

假设我们有一个简单的 Spring 项目,用于处理用户的 CRUD 操作,以下是示例项目的主要结构:

src/main/java└── com└── example├── config│   ├── AppConfig.java│   └── TransactionConfig.xml├── dao│   └── UserDao.java├── entity│   └── User.java├── service│   └── UserService.java└── test└── UserServiceTest.java

一、数据库配置

1. 数据源配置

Java 配置 (AppConfig.java)

package com.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example") // 扫描指定包下的组件
public class AppConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/testdb");dataSource.setUsername("root");dataSource.setPassword("password");return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

XML 配置 (TransactionConfig.xml)

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 数据源配置 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/testdb"/><property name="username" value="root"/><property name="password" value="password"/></bean><!-- JdbcTemplate 配置 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!-- 事务管理器配置 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 启用事务管理 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 扫描包路径 --><context:component-scan base-package="com.example"/>
</beans>

二、实体类

User.java

package com.example.entity;public class User {private int id;private String username;private String password;// Getters and Setterspublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

三、DAO 层

UserDao.java

package com.example.dao;import com.example.entity.User;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;@Repository
public class UserDao {@Autowiredprivate JdbcTemplate jdbcTemplate;public void createUser(User user) {String sql = "INSERT INTO users (username, password) VALUES (?, ?)";jdbcTemplate.update(sql, user.getUsername(), user.getPassword());}public User getUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) -> {User user = new User();user.setId(rs.getInt("id"));user.setUsername(rs.getString("username"));user.setPassword(rs.getString("password"));return user;});}public void updateUser(User user) {String sql = "UPDATE users SET username = ?, password = ? WHERE id = ?";jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), user.getId());}public void deleteUser(int id) {String sql = "DELETE FROM users WHERE id = ?";jdbcTemplate.update(sql, id);}
}

四、服务层

UserService.java

package com.example.service;import com.example.dao.UserDao;
import com.example.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Autowiredprivate UserDao userDao;@Transactionalpublic void createUser(User user) {userDao.createUser(user);// Simulate an exception to test rollbackif ("error".equals(user.getUsername())) {throw new RuntimeException("Simulated exception");}}@Transactionalpublic void updateUser(User user) {userDao.updateUser(user);// Simulate an exception to test rollbackif ("error".equals(user.getUsername())) {throw new RuntimeException("Simulated exception");}}
}

五、测试

UserServiceTest.java

package com.example.test;import com.example.config.AppConfig;
import com.example.entity.User;
import com.example.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;import static org.junit.jupiter.api.Assertions.assertThrows;public class UserServiceTest {@Testpublic void testCreateUserWithTransaction() {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);User user = new User();user.setUsername("normaluser");user.setPassword("password");// Test normal behavioruserService.createUser(user);// Test exception and rollbackUser errorUser = new User();errorUser.setUsername("error");errorUser.setPassword("password");assertThrows(RuntimeException.class, () -> {userService.createUser(errorUser);});}@Testpublic void testUpdateUserWithTransaction() {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);User user = new User();user.setId(1); // assuming user with ID 1 existsuser.setUsername("updateduser");user.setPassword("newpassword");// Test normal behavioruserService.updateUser(user);// Test exception and rollbackUser errorUser = new User();errorUser.setId(1); // assuming user with ID 1 existserrorUser.setUsername("error");errorUser.setPassword("newpassword");assertThrows(RuntimeException.class, () -> {userService.updateUser(errorUser);});}
}

六、总结

  • 配置:数据库连接和事务管理器的配置可以使用 Java 配置或 XML 配置,根据项目需求选择合适的方式。
  • 实体类:定义了与数据库表映射的 Java 类。
  • DAO 层:负责具体的数据库操作,如创建、读取、更新和删除(CRUD)操作。
  • 服务层:封装业务逻辑,并通过 @Transactional 注解来管理事务。
  • 测试:验证事务管理是否按预期工作,测试正常情况下和异常情况下的事务回滚行为。

通过上述示例,您可以清楚地了解如何在 Spring 框架中配置和使用事务管理。这个示例展示了如何通过 Java 配置和 XML 配置来设置事务管理器,如何在服务层使用事务管理,以及如何编写测试用例来验证事务的行为。

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

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

相关文章

Android SurfaceFlinger——GraphicBuffer的提交(三十三)

在 SurfaceFlinger 中,我们 dequeueBuffer 和 queueBuffer 是 Surface 控制接口中非常重要的两个函数,分别用于从 Surface 的 BufferQueue 中取出缓冲区和向 BufferQueue 提交(队列)缓冲区。这两个函数在生产者和消费者模型中扮演着核心角色,确保了图像数据的高效和有序传…

消息队列原理题库

1. 简述什么是消息队列 &#xff1f; 消息&#xff08;Message&#xff09;是指在应用间传送的数据。消息可以非常简单&#xff0c;比如只包含文本字符串&#xff0c;也可以更复杂&#xff0c;可能包含嵌入对象。 消息队列&#xff08;Message Queue&#xff09;是一种应用间…

【算法】子集

难度:中等 题目: 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的 子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 示例 2: 输入…

Spring AI (三) 提示词对象Prompt

3.提示词对象Prompt 3.1.Prompt Prompt类的作用是创建结构化提示词, 实现了ModelRequest<List<Message>>接口 Prompt(String contents)&#xff1a;创建一个包含指定内容的Prompt对象。 Prompt(String contents, ChatOptions modelOptions)&#xff1a;创建一个…

某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC]

文章目录 某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现某数据泄露防护(DLP)系统NoticeAjax接口SQL注入漏洞复现 [附POC] 0x01 前言 免责声明:请勿利用文章内…

DolphinDB Web 端权限管理:可视化操作指南

在现代数据库管理中&#xff0c;高效和直观的权限管理对于用户的数据安全是至关重要的。过去 DolphinDB 用户需要依赖系统脚本来管理用户和权限&#xff0c;这对于缺乏技术背景的管理员来说既复杂又容易出错。 为了提升用户体验和操作效率&#xff0c;DolphinDB 目前在 Web 上…

数据库设计三范式

文章目录 数据库设计三范式第一范式第二范式第三范式一对一怎么设计主键共享外键唯一 一对多怎么设计多对多怎么设计 数据库设计三范式 数据库表设计的原则。教你怎么设计数据库表有效&#xff0c;并且节省空间。 如果客户有速度要求极致&#xff0c;可以不用。根据客户需求来 …

vue3中动态添加form表单校验

<template><div><div v-for"(formData, index) in forms" :key"index"><u-form :model"formData" :rules"rules" ref"formRefs"><u-form-item label"用户名" prop"username"…

MySQL数据库练习(5)

1.建库建表 # 使用数据库 use mydb16_trigger;# 表格goods create table goods( gid char(8) primary key, name varchar(10), price decimal(8,2), num int);# 表格orders create table orders( oid int primary key auto_increment, gid char(10) not null, name varchar(10…

scrapy 爬取旅游景点相关数据(一)

第一节 Scrapy 练习爬取穷游旅游景点 配套视频可以前往B站&#xff1a;https://www.bilibili.com/video/BV1Vx4y147wQ/?vd_source4c338cd1b04806ba681778966b6fbd65 本项目为scrapy 练手项目&#xff0c;爬取的是穷游旅游景点列表数据 0 系统的环境 现在网上可以找到很多scr…

其它------

这里写目录标题 一级目录二级目录三级目录 一级目录 二级目录 三级目录

Pytorch使用教学6-张量的分割与合并

在使用PyTorch时&#xff0c;对张量的分割与合并是不可避免的操作&#xff0c;本节就带大家深刻理解张量的分割与合并。 在开始之前&#xff0c;我们先对张量的维度进行深入理解&#xff1a; t2 torch.zeros((3, 4)) # tensor([[0., 0., 0., 0.], # [0., 0., 0., 0.…

异或和+博弈论

1.最后状态a1a2a3...an0,显然a1^a2^a3...^an0 2.对ai操作&#xff0c;变成new ai,等价于ai异或一个数字x,使得ai^xnew ai 3.因此得出结论&#xff1a;对某一堆石子(ai)的操作实际上等同于对该堆石子的异或 4.当前我的状况&#xff1a;a1^a2^a3...^an0,假设上一步,你的状况a1^a2…

C语言边界互通传送迷宫

目录 注意事项开头程序程序的流程图程序输入与输出的效果结尾 注意事项 程序里有关字符’\033’的输出都关于Sunshine-Linux的其中一篇博客——《printf函数高级用法设置打印字体颜色和背景色等》 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们来看一下我用C语…

现代Java开发:使用jjwt实现JWT认证

前言 jjwt 库 是一个流行的 Java 库&#xff0c;用于创建和解析 JWT。我在学习spring security 的过程中看到了很多关于jwt的教程&#xff0c;其中最流行的就是使用jjwt实现jwt认证&#xff0c;但是教程之中依然使用的旧版的jjwt库&#xff0c;许多的类与方法已经标记弃用或者…

“分布式” 和 “集群”

“分布式” 和 “集群” 是计算机系统领域中的两个重要概念&#xff0c;它们在设计和实现现代计算架构时经常被提到。虽然它们有重叠之处&#xff0c;但也有显著的区别。 集群&#xff08;Cluster&#xff09; 集群 是由多个计算节点&#xff08;通常是计算机或服务器&#x…

国科大《人工智能原理与算法》2021年期末试题+2024经验(2025指南)

启发式路径算法(Pohl,1977)是一种最佳优先搜索,它的评估函数是: f(n)=(2−w)⋅g(n)+w⋅h(n)f(n)=(2−w)⋅g(n)+w⋅h(n) 假设 hh 是可采纳的。 ww 取什么值能保证算法是最优的?当 w=0w=0,w=1w=1,w=2w=2 时,分别是什么搜索算法?本题以并字棋(圈与十字游戏)为例练习博…

InsCode GPU服务器快速使用

文章目录 1. 背景介绍2. 环境配置 1. 背景介绍 InsCode服务器地址&#xff1a;https://inscode.csdn.net/workbench?tabcomputed。 2. 环境配置 新建环境后&#xff0c;按照如下步骤快速配置&#xff0c;以便后续执行深度学习模型训练。 数据 openlane 环境依赖 Copy Mini…

数据结构与算法--顺序表(Java)

&#x1f4dd;个人主页&#x1f339;&#xff1a;誓则盟约 ⏩收录专栏⏪&#xff1a;Java SE &#x1f921;往期回顾&#x1f921;&#xff1a;Java SE--基本数据类型&#xff08;详细讲解&#xff09; &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 什么…

【Python面试题收录】Python编程基础练习题②(数据类型+文件操作+时间操作)

本文所有代码打包在Gitee仓库中https://gitee.com/wx114/Python-Interview-Questions 一、数据类型 第一题 编写一个函数&#xff0c;实现&#xff1a;先去除左右空白符&#xff0c;自动检测输入的数据类型&#xff0c;如果是整数就转换成二进制形式并返回出结果&#xff1b…