昆明网站建设公司哪家好,中国工程局人才招聘网,惠州网站公司,邢台做网站可信赖1.调用这个方法的对象是否是spring的代理对象#xff08;$CGLIB结尾的#xff09;
2.这个方法是否是加了Transactional注释
都符合才可以被事物控制 如果调用方法的对象没有被事物控制#xff0c;那么被调用的方法即便是加了Transactional也是没用的 事务失效情况#xf…1.调用这个方法的对象是否是spring的代理对象$CGLIB结尾的
2.这个方法是否是加了Transactional注释
都符合才可以被事物控制 如果调用方法的对象没有被事物控制那么被调用的方法即便是加了Transactional也是没用的 事务失效情况 解释说明
1基于aop的环绕通知的方式如果抛出了异常给spring框架和代理对象就会进行事物的回滚而如果调用这个方法的时候把异常捕获到了并没有抛出就会导致事务无法回滚。 3事务方法调用事务方法 如果在事务对象内部直接调用另一个事务方法那么是会进行事务传递的被调用的事务方法是会被当成和调用方一个整体的事务。并且被调用的事务不可以新开启一个事务也就是说被调用的事务上方加上如下注释是不起作用的 5可以自行定义事务抛出什么类型的异常才能回滚 一个非事务方法调同类一个事务方法事务无法控制举例如下
在controller中调用MediaFileServiceImpl 中的uploadFile方法因为controller中注入了Autowired MediaFileService mediaFileService;所以controller将被spring代理对象代理此时如果MediaFileServiceImpl中的 uploadFile加了Transactional注释那么很自然的将受到事物控制。验证是否是spring的代理对象可以debug然后查看变量是否是$CGLIB结尾的。 如果在uploadFile方法上没有Transactional注解代理对象执行此方法前不进行事务控制如下图 现在在addMediaFilesToDb方法上添加Transactional注解也不会进行事务是因为并不是通过代理对象执行的addMediaFilesToDb方法。为了判断在uploadFile方法中去调用addMediaFilesToDb方法是否是通过代理对象去调用我们可以打断点跟踪。 controller代码如下在try catch中看到用的是mediaFileService去调用的uploadFile方法此时是可以控制事物的。
public class MediaFilesController {Autowired
MediaFileService mediaFileService;RequestMapping(value /upload/coursefile, consumes {MediaType.MULTIPART_FORM_DATA_VALUE})public UploadFileResultDto upload(RequestPart(filedata) MultipartFile filedata,RequestParam(value folder,requiredfalse) String folder,RequestParam(value objectName,requiredfalse) String objectName) {Long companyId 1232141425L;UploadFileParamsDto uploadFileParamsDto new UploadFileParamsDto();String contentType filedata.getContentType();uploadFileParamsDto.setContentType(contentType);uploadFileParamsDto.setFileSize(filedata.getSize());//文件大小if (contentType.indexOf(image) 0) {//是个图片uploadFileParamsDto.setFileType(001001);} else {uploadFileParamsDto.setFileType(001003);}uploadFileParamsDto.setFilename(filedata.getOriginalFilename());//文件名称UploadFileResultDto uploadFileResultDto null;try {uploadFileResultDto mediaFileService.uploadFile(companyId, uploadFileParamsDto, filedata.getBytes(), folder, objectName);} catch (Exception e) {XueChengPlusException.cast(上传文件过程中出错);}return uploadFileResultDto;}如果在uploadFile方法中取调用另外一个方法那么显然调用的对象默认是this并不是受到spring代理的对象所以即便被uploadFile方法调用的方法加了Transactional注释也是没用的。 解决非代理对象调用Transactional方法的
我们可以模仿Controller中的写法在被调用的方法中注入相应的service然后用service在非事物方法中取调用加了Transactional注释的方法这样事物是会生效的。
下面举例
在serviceimpl类中的uploadFile方法调用另一个Transactional方法形成事物
首先在serviceimpl中注入service对象对象名字无所谓加了Autowired注释的对象会被AOP拦截 AutowiredMediaFileService proxy;
调用方法在try代码第2行用proxy调用
Overridepublic UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, byte[] bytes, String folder, String objectName) {....try {addMediaFilesToMinIO(bytes,bucket_files,objectName);MediaFiles mediaFiles proxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_files, objectName);//准备返回数据UploadFileResultDto uploadFileResultDto new UploadFileResultDto();BeanUtils.copyProperties(mediaFiles,uploadFileResultDto);return uploadFileResultDto;} catch (Exception e) {log.debug(上传文件失败{},e.getMessage());throw new RuntimeException(e.getMessage());}// return null;}
被调用的方法
Transactional
public MediaFiles addMediaFilesToDb(Long companyId, String fileId, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName) {//保存到数据库MediaFiles mediaFiles mediaFilesMapper.selectById(fileId);if(mediaFiles null){mediaFiles new MediaFiles();//封装数据BeanUtils.copyProperties(uploadFileParamsDto,mediaFiles);mediaFiles.setId(fileId);mediaFiles.setFileId(fileId);mediaFiles.setCompanyId(companyId);mediaFiles.setBucket(bucket);mediaFiles.setFilePath(objectName);mediaFiles.setUrl(/bucket/objectName);mediaFiles.setCreateDate(LocalDateTime.now());mediaFiles.setStatus(1);mediaFiles.setAuditStatus(002003);//插入文件表mediaFilesMapper.insert(mediaFiles);}return mediaFiles;}注意我们这里由于是用的service来调用而service是一个接口所以被proxy调用的方法必须也是以接口形式呈现出来那么需要将addMediaFilesToDb写入到对应调用这个方法的service此处用MediaFileService proxy调用所以在MediaFileService 中加上这个方法写个接口即可。
接口如下
public interface MediaFileService {
/***
* description 上传文件到数据库抽取为接口的形式方便调用
* param companyId* param fileId* param uploadFileParamsDto* param bucket* param objectName
* return
* author
* date
*/public MediaFiles addMediaFilesToDb(Long companyId, String fileId, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName);
}