为什么我得到TransactionRequired异常,甚至方法保存实体用@Transactional注释?

时间:2017-12-16 03:10:08

标签: java spring spring-mvc jpa spring-data

上传图片时出现异常

方法

 public ServiceResult uploadPortrait( MultipartFile file,int userId){
    if (file.getSize()>ConfigurationHolder.getPictureSize()) {
        return ServiceResult.getErrorResult("exceed 2M!");
    }else{
        String filename=file.getOriginalFilename();
        String subfix=FileType.getSuffixByFilename(filename);
        if(ConfigurationHolder.getPortraitFileType().contains(subfix)){
            String inLibPath=ConfigurationHolder.getUserPortraitInLibPath(userId, subfix);
            try { 
                savePortraitToDataBase(inLibPath, userId);
            } catch (Exception e) {
                e.printStackTrace();
                return ServiceResult.getErrorResult("saveError!");
            }
            ServiceResult result=ServiceResult.getSuccessResult("changeSuccess!");
            result.putProperty("portraitPath", inLibPath);
            return result;
        }else{
            return ServiceResult.getErrorResult("file type must be one of jpg,png,jpeg or gif!");
        }
    }
}
@Transactional(value="account",rollbackFor=Exception.class)
public void savePortraitToDataBase(String inLibPath, int userId){
    userOthersRepos.updatePortait(userId,inLibPath);
    userOthersdao.savePortraitToRedis(inLibPath, userId);
}

异常

Caused by:exception'stacktrace:Caused by:javax.persistence.TransactionRequiredException: Executing an update/delete query
        at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:372)
        at $Proxy118.executeUpdate(Unknown Source)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:174)
        at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:61)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:95)
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:85)
        at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:323)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
        ... 79 more 

当我将@Transactional注释添加到uploadPortrait()并将其从savePortraitToDataBase()中删除时,它就有效。

有人可以告诉我为什么吗?

2 个答案:

答案 0 :(得分:0)

在上面的代码片段中,您从“uploadPortrait”调用“savePortraitToDataBase”方法,在此调用之前,您调用“userOthersdao.savePortrait”。在我看来,你得到的异常是因为userOthersdao.savePortrait的调用(因为它也可能正在执行插入/更新操作,并且如果将@Transactional放在savePortraitToDataBase这个方法上,则会丢失事务。)

但另一方面,当您将@Transactional放在“uploadPortrait”函数上时,两种方法都可以使用事务。

答案 1 :(得分:0)

对@ chrylis的评论进行阐述," Transactional" annotation是一个Spring装饰器 - 它只适用于通过注入(或者#34; autowired",在弹簧术语中)bean从类外部调用到函数的东西。从同一个班级内部打电话不会产生同样的效果