Spring @Transactional 传播不起作用

Pra*_*tap 0 spring hibernate transactions transactional spring-transactions

我有一个非常简单的代码,由 Service -> RequestProcessor -> DAO 组成,每层有 2-3 个类(接口、抽象、具体)。

服务层:-

public interface Service {
   public void saveOrUpdate(Object entity, String operationName);
 }
}

public abstract class AbstractService implements Service{

   public abstract ReqProcessor getRP();
   @Override
   public void saveOrUpdate(Object entity, String operationName) {
     ReqProcessor hiberTestRP = getRP();
     hiberTestRP.saveOrUpdate(entity, operationName);
 }
}

@Component
public class ServiceImpl extends AbstractService {

  @Autowired
  public ReqProcessor hibertestRPImpl;

  @Override
  public HiberTestRP getRP() {
    return hibertestRPImpl;
 }
}
Run Code Online (Sandbox Code Playgroud)

ReqProcessor 层:-

public interface ReqProcessor {
   public void saveOrUpdate(Object entity, String operationName);
   public void saveObject();
 }
}

public abstract class AbstractReqProcessor  implements ReqProcessor {
@Override
public void saveOrUpdate(Object entity, String operationName) {
    saveObject();
 }
}

@Component
public class ReqProcessorImpl extends AbstractReqProcessor {
 @Autowired
 public CustomHibernateDao customWSDaoImpl;

 @Override
 @Transactional(value="transactionManagerWS", propagation=Propagation.REQUIRED)
 public void saveObject() {
  // object created //
  customWSDaoImpl.saveOrUpdate(object);  // exception is thrown at this line
 }
}
Run Code Online (Sandbox Code Playgroud)

DAO 层:-

public interface CustomHibernateDao {
  public void saveOrUpdate(Object entity, String operationName);
}

@Repository
@Transactional(value="transactionManagerWS", propagation=Propagation.MANDATORY)
public class CustomWSDaoImpl implements CustomHibernateDao {

 @Autowired
 public SessionFactory sessionFactoryWS;

 protected Session getCurrentSession() {
    return sessionFactoryWS.getCurrentSession();
 }

 @Override
 public void saveOrUpdate(Object entity, String operationName) {
    Session session = getCurrentSession();
    session.saveOrUpdate(entity);
 }
}
Run Code Online (Sandbox Code Playgroud)

我在注释行中收到以下异常:

Exception in thread "main" org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:359)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy37.saveOrUpdate(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

当抽象类被删除时,代码工作得非常好,只留下接口及其实现类。但通过上述设置,事务不会从 ReqProcessor 层传播到 DAO 层。请帮忙。(不要介意到处都是“公共”访问器,它只是为了测试)我也在 SO 和其他论坛上搜索过,但找不到解决方案。

Rom*_*hin 5

@Transactional正如 @m-deinum 所提到的,Spring 使用代理来添加“事务”功能,并且当您从类的另一个方法调用带有注释的方法时,此功能不起作用。

您有两种方法可以解决该问题:

  1. AbstractReqProcessorautowire中ApplicationContext然后用它来获取一个bean的CustomHibernateDao类型。您可以在这个检索到的对象上调用saveObject- 然后transactional神奇的事情就会发生。
  2. 更优选的方法是也用注释来注释saveOrUpdate类的方法- 然后它会再次工作。AbstractService@Transactional

但我想你现在已经知道问题的原因了,你可以找到另一种——更适合你的——方式。