【问题标题】:How to call @Transactional method from one service from other @Transactional method from other service如何从另一个服务的另一个@Transactional方法调用一个服务的@Transactional方法
【发布时间】:2014-05-13 21:23:05
【问题描述】:

我有:

1) 服务:

@Service("scanner")
@Transactional
public class Scanner
{
    @Inject
    AnalyzerService analyzerService;

    @Transactional
    private void scan() {
        analyzerService.analyze();
    }
}

2) 服务:

@Service
public class AnalyzerService
{
    @Inject
    AnalyzerDao analyzerDao;

    @Transactional
    public void analyze() {
        List<AnalyzerResult> items;
        // code filling items list removed;
        save(items); 
    }

    @Transactional
    private void save(List<SomeType> items) {
        analyzerDao.save(items); // <--- Why after call save items are not saved in DB?
    }
}

3) 道:

@Repository
public class AnalyzerDao extends GenericDaoImpl<AnalyzerResult>
{
    //all needed methods for find, edit, delete and save which works fine in other cases.
}

问题:

为什么调用analzyerDao.save(items)后数据库还是空的?交易有问题吗? 当我在analyzerDao.save(items) 行之后调用flush() 方法和getSession().getTransaction().commit() 时,记录出现在数据库中但抛出异常:

Caused by: org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:660)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at com.sun.proxy.$Proxy44.execute(Unknown Source)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
    ... 1 more
Caused by: org.hibernate.TransactionException: Transaction not successfully started
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:127)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
    ... 9 more

应该如何实施才能使“保存”方法正常工作? 我应该怎么做才能只在analyzerDao.save(items) 中保存项目,而不仅仅是在第一次交易完成之后?

【问题讨论】:

    标签: spring transactions spring-transactions


    【解决方案1】:

    你需要的是一个新的交易,只是为了保存你需要保存的东西。可以通过将@Transactional注解的propagation配置为REQUIRES_NEW来实现。

    不幸的是,您的情况有点棘手,因为您在执行save(items); 时正在调用this 上下文中的方法,这意味着事务拦截器不会拦截此类调用,因此您可以将服务注入到一个字段自己持有并在注入的服务上调用它,而不是强制对该方法的调用被事务拦截器拦截,请尝试以下实现:

    @Service
    public class DefaultAnalyzerService implements AnalyzerService {
        @Inject
        AnalyzerDao analyzerDao;
        @Inject
        AnalyzerService analyserService;
    
        @Transactional
        @Override
        public void analyze() {
            List<AnalyzerResult> items;
            // code filling items list removed;
            analyserService.save(items); 
        }
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        @Override
        public void save(List<SomeType> items) {
            analyzerDao.save(items); // <--- Why after call save items are not saved in DB?
        }
    
    }
    

    另一个改变是save(List&lt;SomeType&gt; items) 的可见性,它现在是公开的,以便被事务拦截器拦截并提取接口。由于 spring 的限制,这是需要的,但是您可以使用 AspectJ 来处理此类拦截器,因此请查看here

    【讨论】:

      【解决方案2】:

      在事务提交之前,数据不会出现在数据库中。对于@Transactional 方法,事务由 Spring 从方法返回之后提交。

      顺便说一句,私有方法上的@Transactional 没有效果,所以Scanner.scan() 根本不是事务性的。

      【讨论】:

        猜你喜欢
        • 2018-02-23
        • 2011-09-07
        • 2011-07-03
        • 1970-01-01
        • 1970-01-01
        • 2021-07-02
        • 2020-07-08
        • 1970-01-01
        • 2012-07-01
        相关资源
        最近更新 更多