在Java中经常遇到一个非事务方法调同类一个事务方法,事务无法控制,这是为什么呢?
- 因为事务是通过代理加aop实现的
如下:为什么不把事务放在 uploadFile 方法上,因为 addMediaFilesToMinIO 需要通过网络连接 minio ,如果网络不好连不上,事务就会占据数据库比较长的时间,这是没有必要的,所以我们把事务放在操作数据库的方法 addMediaFilesToDb 上
那么下面在 uploadFile 调用 addMediaFilesToDb 方法,事务能实现吗,不能,因为事务本身是通过代理对象来调用的,而 MediaFileServiceImpl 本身 this 并不是代理对象
...
import org.springframework.transaction.annotation.Transactional;
@Service
public class MediaFileServiceImpl implements MediaFileService {
@Override
public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath) {
...
// 6.上传文件到minio
boolean result = addMediaFilesToMinIO(localFilePath, mimeType, bucket_mediafiles, objectName);
...
// 7.将文件信息保存到数据库
MediaFiles mediaFiles = addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName);
// 相当于this.addMediaFilesToDb()
...
}
/**
* @description 将文件信息添加到文件表
*/
@Transactional
public MediaFiles addMediaFilesToDb(Long companyId, String fileMd5, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName) {
mediaFiles = new MediaFiles();
...映射数据
//插入数据库
int insert = mediaFilesMapper.insert(mediaFiles);
...
}
}
所以,我们要怎么使上面的方法实现事务呢?注入本身即可
- 在
service中定义addMediaFilesToDb方法,使注入自己的service能够调用
public interface MediaFileService {
public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath);
public MediaFiles addMediaFilesToDb(Long companyId, String fileMd5, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName);
}
- 在
impl中使用实现事务,用currentProxy调用addMediaFilesToDb即可
...
import org.springframework.transaction.annotation.Transactional;
@Service
public class MediaFileServiceImpl implements MediaFileService {
// 注入自己实现代理,springboot注入会自动给我们包裹代理
@Autowired
MediaFileService currentProxy;
@Override
public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath) {
...
// 7.将文件信息保存到数据库
MediaFiles mediaFiles = currentProxy.addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_mediafiles, objectName);
...
}
@Transactional
public MediaFiles addMediaFilesToDb(Long companyId, String fileMd5, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName) {
mediaFiles = new MediaFiles();
...映射数据
//插入数据库
int insert = mediaFilesMapper.insert(mediaFiles);
...
}
}