Spring 事务失效

总结点 什么情况下会导致事务失效

代理对象调用
方法上添加Transcation 注解 采用声明式事务
1)方法中捕获异常没有抛出
spring控制事务式基于AOP环绕通知实现的,如果方法抛出了异常就会回滚,如果没有抛出就不会生效
2)非事务方法调用事务方法
在内部调用由于不是代理对象,因此失效
3)事务方法调用事务方法
可以被控制 但要选对事务传播行为 只要不是通过代理对象去掉 那么开启一个新事务是不可能的
4)transaction 如果标记的不是public 方法也不可以
5)抛出的异常类型 默认是RuntimeException
6) 数据库本身不支持事务 例如mysql 的myisam存储引擎
7)传播行为导致事务失效 比如某些事务传播行为 压根不支持事务

下面给出一个非事务方法调用事务方法时 不是代理对象的解决方案

方案一 编程式事务
这个就没什么好说的了,网上很多

方案二 声明式事务
首先分析原因式因为没有采用代理对象调用,因为该事务方法与非事务方法定义在一个service中,那么就需要想办法将其变为代理对象调用,我们知道注入的对象为代理对象,因此在本service中注入本service。
但是又引申出另一个问题,本service 注入本service 会造成循环依赖,本循环依赖并不会通过spring 三级缓存解决,需要使用@Lazy 注解延迟加载来打破循环依赖。
补充:什么是三级缓存
第一级 单例对象缓存池,已经实例化并且属性赋值,存放成熟对象
第二级 单例对象缓存池,已经实例化但尚未付属性值,存放半成品对象
第三级 单例工厂的缓存

package com.jhj.media.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.jhj.base.exception.UltimateException;
import com.jhj.base.model.PageParams;
import com.jhj.base.model.PageResult;
import com.jhj.media.mapper.MediaFilesMapper;
import com.jhj.media.model.dto.QueryMediaParamsDto;
import com.jhj.media.model.dto.UploadFileParamsDto;
import com.jhj.media.model.dto.UploadFileResultDto;
import com.jhj.media.model.po.MediaFiles;
import com.jhj.media.service.MediaFileService;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;/*** @author jhj* @version 1.0* @description TODO* @date 2022/9/10 8:58*/
@Service
@Slf4j
public class MediaFileServiceImpl implements MediaFileService {@AutowiredMediaFilesMapper mediaFilesMapper;@AutowiredMinioClient minioClient;@Autowired@LazyMediaFileService currentProxy;//存储普通文件@Value("${minio.bucket.files}")private String bucket_mediafiles;//存储视频@Value("${minio.bucket.videofiles}")private String bucket_video;@Overridepublic PageResult<MediaFiles> queryMediaFiels(Long companyId, PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto) {//构建查询条件对象LambdaQueryWrapper<MediaFiles> queryWrapper = new LambdaQueryWrapper<>();//分页对象Page<MediaFiles> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());// 查询数据内容获得结果Page<MediaFiles> pageResult = mediaFilesMapper.selectPage(page, queryWrapper);// 获取数据列表List<MediaFiles> list = pageResult.getRecords();// 获取数据总数long total = pageResult.getTotal();// 构建结果集PageResult<MediaFiles> mediaListResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize());return mediaListResult;}@Override//为什么不在这里加事务 是因为防止minio 网络连接时间长而导致数据库连接超时 占用数据库事务资源public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath) {//文件名String filename = uploadFileParamsDto.getFilename();//拿到扩展名String extension = filename.substring(filename.lastIndexOf("."));//拿到mimeTypeString mimeType = getMimeType(extension);//文件的md5String fileMd5 = getFileMd5(new File(localFilePath));//目录String defaultFolderPath = getDefaultFolderPath();String objectName = defaultFolderPath + fileMd5 + extension;//将文件上传Minioboolean result = addMediaFilesToMinio(localFilePath, mimeType, bucket_mediafiles, objectName);if(!result){UltimateException.cast("上传文件失败");}//将文件信息保存到数据库MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName);if(mediaFiles==null){UltimateException.cast("文件上传后,保存信息失败");}//返回对象UploadFileResultDto uploadFileResultDto = new UploadFileResultDto();BeanUtils.copyProperties(mediaFiles,uploadFileResultDto);return uploadFileResultDto;}//根据扩展名获取mimeTypeprivate String getMimeType(String extension) {if (extension == null) {extension = "";}ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE; //通用mimeTypeif (extensionMatch != null) {mimeType = extensionMatch.getMimeType();}return mimeType;}/*** 将文件上传到minio* @param localFilePath 本地路径* @param mimeType 媒体类型* @param bucket 桶* @param objectName 文件名* @return*/private boolean addMediaFilesToMinio(String localFilePath, String mimeType, String bucket, String objectName) {try {minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucket).filename(localFilePath).object(objectName).contentType(mimeType).bucket(bucket).build());log.debug("上传文件到minio成功,bucket:{},objectName:{}",bucket,objectName);return true;} catch (Exception e) {e.printStackTrace();log.error("上传文件出错,bucket:{},objectName:{},错误信息:{}",bucket,objectName,e.getMessage());}return false;}private String getDefaultFolderPath(){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");String folder = sdf.format(new Date()).replace("-", "/") + "/";return folder;}private String getFileMd5(File file){try(FileInputStream fileInputStream=new FileInputStream(file)){String fileMd5 = DigestUtils.md5Hex(fileInputStream);return fileMd5;}catch (Exception e){e.printStackTrace();return null;}}/*** 将文件信息保存到数据库* @param companyId 机构id* @param fileMd5 md5* @param uploadFileParamsDto 文件信息* @param bucket 桶信息* @param objectName 路径* @return*/@Transactional//事务只能用于public 方法 原理是Aop jdk cglib 两种方式 访问不了private//注意看是不是被代理对象调用 如果不是 则事务不会生效//同serive 调用同类的事务方法 事务是无法控制的 因为用的是this 并不是代理对象//注入进去的都是代理对象 this就是对象本身 解决办法 把service 在本类中进行注入public MediaFiles addMediaFilesToDb(Long companyId, String fileMd5, UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName){MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5);if (mediaFiles == null){mediaFiles=new MediaFiles();BeanUtils.copyProperties(uploadFileParamsDto,mediaFiles);//文件idmediaFiles.setId(fileMd5);mediaFiles.setFileId(fileMd5);//机构idmediaFiles.setCompanyId(companyId);//桶mediaFiles.setBucket(bucket);//file_pathmediaFiles.setFilePath(objectName);//urlmediaFiles.setUrl("/"+bucket+"/"+objectName);//上传时间mediaFiles.setCreateDate(LocalDateTime.now());//状态mediaFiles.setStatus("1");//审核状态mediaFiles.setAuditStatus("002003");//插入数据库int insert = mediaFilesMapper.insert(mediaFiles);int i=1/0;if(insert<0){log.error("向数据库保存文件失败,bucket:{},objectName:{}",bucket,objectName);return null;}return mediaFiles;}return mediaFiles;}
}

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

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

相关文章

Ruby 注释

Ruby 注释 在编程中&#xff0c;注释是用于解释代码如何工作以及为什么这样编写的重要工具。Ruby作为一种解释型、面向对象的脚本语言&#xff0c;提供了灵活的注释方式&#xff0c;帮助开发者更好地组织和理解代码。本文将详细介绍Ruby中的注释类型、用法以及最佳实践。 Rub…

[极客大挑战 2020]Roamphp2-Myblog

又来喽 经过一番测试&#xff0c;发现文件包含&#xff0c;使用伪协议读取文件 例&#xff1a;php://filter/readconvert.base64-encode/resourcelogin //这里我只写php部分 //login.php <?php require_once("secret.php"); mt_srand($secret_seed); $_SESSION…

深入探索Netty的零拷贝技术:实现原理与应用详解

深入探索Netty的零拷贝技术&#xff1a;实现原理与应用详解 1. 什么是零拷贝技术&#xff1f; 零拷贝技术是指在数据传输过程中&#xff0c;尽量避免数据在内存之间的复制&#xff0c;从而减少 CPU 的拷贝时间和数据传输延迟。传统的数据传输通常需要将数据从一个内存缓冲区拷…

FPGA国内”薪“赛道-在医疗领域的应用

mian 免 ze 责 sheng 声 ming 明 以下观点仅代表个人观点&#xff0c;不代表任何公司或者行业 从下游应用市场来看&#xff0c;通信和工业市场份额位居FPGA芯片一二位&#xff0c;同时通信市场份额有望持续提升。但是目前通信和工业市场趋于稳定&#xff0c;FPGA厂商一直推AI市…

SpringBoot 实现RequestBodyAdvice封装统一接受类功能

一、相关往期文章 SpringBootVue实现AOP系统日志功能_aop的vue完整项目 Spring AOP (面向切面编程&#xff09;原理与代理模式—实例演示_面向切面aop原理详解 二、需求分析 按照一般情况&#xff0c;统一接受类可以像以下的方式进行处理&#xff1a; 如果不想使用 Request…

Vue75-路由传参3

一、在index.js中使用props参数 1-1、写法一&#xff1a;值为对象 此时&#xff0c;参数是固定写死的&#xff0c;不推荐&#xff01; 1-2、值为布尔值 此时只能收到params中的参数&#xff01; 1-3、值为函数 &#xff08;最强大&#xff09; 二、小结

maven仓库推送报401 Content access is protected by token

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ 本地很久配置好了往maven中央仓库推送jar包的配置&#xff0c;突然间报如下错误 [ERROR] Failed to execute goal org.sonatype.plugi…

火车头采集器Typecho采集发布模块插件

火车头采集器发布数据到Typecho系统网站应该怎么操作&#xff1f; 1. 火车头采集器Typecho采集发布插件下载安装&#xff1a; 火车头采集器Typecho采集发布模块插件下载地址-CSDN 2. 在火车头采集器软件导Typecho采集发布模块插件&#xff1b; 3. 填写Typecho系统文章对应的…

计算机视觉:2023 年回顾和 2024 年趋势

计算机视觉 (CV) 领域经历了充满非凡创新和技术飞跃的一年。这一年见证了人工智能驱动的视觉技术的显著进步&#xff0c;深刻改变了我们对视觉数据的交互和解读。从生成式人工智能奇迹到复杂的分析工具&#xff0c;CV 不仅不断发展&#xff0c;而且重新定义了其界限。 2023 年 …

从零开始的Ollama指南:部署私域大模型

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…

跨行业数据资产共享与协同:构建一体化数据共享平台,解锁数据资产潜力,促进多行业数据流通与深度应用,共创数字化转型新篇章,引领行业发展新趋势,开启智慧互联新纪元

一、引言 随着信息技术的飞速发展&#xff0c;数据已成为推动社会进步和经济发展的关键要素。然而&#xff0c;在传统行业领域&#xff0c;数据往往被限制在各自的“孤岛”中&#xff0c;难以实现跨行业的流通与共享。这不仅限制了数据的价值发挥&#xff0c;也阻碍了行业的创…

【Apache Doris】如何实现高并发点查?(原理+实践全析)

【Apache Doris】如何实现高并发点查&#xff1f;&#xff08;原理实践全析&#xff09; 一、背景说明二、原理介绍三、环境信息四、Jmeter初始化五、参数预调六、用例准备七、高并发实测八、影响因素九、总结 本文主要分享 Apache Doris 是如何实现高并发点查的&#xff0c;以…

【pytorch02】手写数字问题引入

1.数据集 现实生活中遇到的问题 车牌识别身份证号码识别快递单的识别 都会涉及到数字识别 MNIST&#xff08;收集了很多人手写的0到9数字的图片&#xff09; 每个数字拥有7000个图像train/test splitting:60k vs 10k 图片大小28 28 数据集划分成训练集和测试集合的意义…

推荐4款电脑软件,简单已入手,关键是免费,建议收藏

拖把更名器 拖把更名器是一款功能强大的文件名称修改工具&#xff0c;主要用于批量进行文件更名和整理音乐文件标签。该软件结合资源管理器右键菜单&#xff0c;支持多种文件格式和操作方式&#xff0c;包括MP3、RM、RMVB、WMA等标签更名&#xff0c;文件名、标签内码转换、繁简…

threeJS 基础 03---动画

1.动画效果渲染循环 注&#xff1a; 使用循环渲染时&#xff0c;不用手动渲染到画布且再次调用监听更新事件&#xff0c;两者只用使用其中之一即可 周期循环&#xff0c;默认理想状态下每秒循环60次 requestAnimationFrame 渲染帧率&#xff08;详情见threeJs的文档&#xff…

VUE\JS处理在循环中异步和同步执行的问题

业务场景&#xff1a; 1、有一个组别集合&#xff0c;每一个小组别对象里面有一个数据集合&#xff0c;需要循环去校验每个不同组里的数据&#xff08;不同组合因为一些特殊属性不能合并到一个组里&#xff09;&#xff0c;全都符合就通过验证&#xff0c;去处理后续业务。 2、…

五种主流数据库连接池的比较和分析(从零入门)

数据库连接池&#xff08;Database Connection Pool&#xff09;是现代应用程序中至关重要的组件。它通过管理一组数据库连接的复用&#xff0c;极大地提升了应用程序的性能和效率。在没有连接池的情况下&#xff0c;每个数据库请求都需要打开和关闭数据库连接&#xff0c;这不…

Python编辑器pycharm详细安装步骤

PyCharm 的详细安装步骤 以下是在 Windows 系统上安装 PyCharm 的详细步骤&#xff1a; 第一步&#xff1a;下载安装程序 访问 PyCharm 官方网站&#xff08;https://www.jetbrains.com/pycharm/&#xff09;&#xff0c;根据自己的需求选择社区版&#xff08;Community&…

内容安全复习 6 - 白帽子安全漏洞挖掘披露的法律风险

文章目录 安全漏洞的法律概念界定安全漏洞特征白帽子安全漏洞挖掘面临的法律风险“白帽子”安全漏洞挖掘的风险根源“白帽子”的主体边界授权行为边界关键结论 安全漏洞的法律概念界定 可以被利用来破坏所在系统的网络或信息安全的缺陷或错误&#xff1b;被利用的网络缺陷、错…

车辆轨迹预测系列 (三):nuScenes数据集详细介绍-1

车辆轨迹预测系列 (三)&#xff1a;nuScenes数据集详细介绍-1 文章目录 车辆轨迹预测系列 (三)&#xff1a;nuScenes数据集详细介绍-1一、数据集准备1、解压2、安装nuscenes-devkit3、介绍 二、架构内容解释1、category 类别2、attribute 属性3、visibility 可见性4、instance …