Spring3 的 @Transactional @Scheduled 没有提交给 DB? [英] Spring3 's @Transactional @Scheduled not committed to DB?

查看:27
本文介绍了Spring3 的 @Transactional @Scheduled 没有提交给 DB?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我第一次尝试 Spring3 的 @Scheduled ,但发现我无法提交给 DB.这是我的代码:

This is my 1st time trying Spring3's @Scheduled , but found I cannot commit to DB. This is my code :

@Service
public class ServiceImpl implements Service , Serializable
{
  @Inject 
  private Dao dao;

  @Override
  @Scheduled(cron="0 0 * * * ?") 
  @Transactional(rollbackFor=Exception.class)
  public void hourly()
  {
    // get xxx from dao , modify it
    dao.update(xxx);
  }
}

我认为它应该可以工作,我可以看到它每小时启动一次并从 DB 加载 xxx,但数据未提交到 DB.

I think it should work , I can see it starts-up hourly and load xxx from DB , but data is not committed to DB.

spring 的 xml 中有 tx:annotation-driven :

There's been tx:annotation-driven in spring's xml :

<bean id="entityManagerFactoryApp" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceUnitName" value="myapp"/>
</bean>
<bean id="transactionManagerApp" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="entityManagerFactoryApp" />
</bean>

<tx:annotation-driven transaction-manager="transactionManagerApp" />

谁能告诉我我在这里错过了什么?

Can somebody tell me what I missed here ?

我有一个"解决方案:

@Service
public class ServiceImpl implements Service , Serializable
{
  @Inject 
  private Dao dao;

  @Inject
  @Qualifier("transactionManagerApp")
  private PlatformTransactionManager txMgrApp;

  @Override
  @Scheduled(cron="0 0 * * * ?")
  @Transactional(rollbackFor=Exception.class)
  public void hourly()
  {
    final TransactionTemplate txTemplateApp = new TransactionTemplate(txMgrApp);
    txTemplateApp.execute(new TransactionCallbackWithoutResult()
    {
      @Override
      protected void doInTransactionWithoutResult(TransactionStatus status)
      {
        //get xxx from dao
        dao.update(xxx);
      }
    });
  }
}

工作正常在这里,但它是多余的,使代码更难阅读.我想知道为什么在前面的代码片段中没有注入(并打开)TransactionManager?

It works fine here , but it is so redundant , making the code harder to read. I wonder why TransactionManager is not injected (and opened) in the previous code snippets?

非常感谢!

推荐答案

您可能已经想通了或继续前进(我希望如此),但为了他人的利益:

You probably have figured this out or moved on (I hope so), but for the benefit of others:

@Transactional 注释告诉 Spring 用一个动态代理包装你原来的 ServiceImpl bean,该代理也实现了Service"(默认情况下 Spring代理接口,而不是实现).当您在代理上调用 hourly() 时,此代理将透明地处理事务的创建和提交/回滚.但是,如果您直接在您的实现上调用 hourly()(这是上面发生的事情),代理将被绕过,因此没有交易.

The @Transactional annotation tells Spring to wrap your original ServiceImpl bean with a dynamic proxy that also implements 'Service' (by default Spring proxies the interface, not the implementation). This proxy will transparently handle the creation and commit/rollback of the transaction when you call hourly() on the proxy. However, if you call hourly() directly on your implementation (which is what is happening above), the proxy is bypassed, so there is no transaction.

http://blog.springsource.org/2012/05/23/understanding-proxy-usage-in-spring/

解决办法是要么

  1. 像您在脏"解决方案中所做的那样,以编程方式划分事务(在这种情况下您不需要注释).
  2. 确保您的@Scheduled 方法通过服务接口调用dao.update(xxx);,而不是直接在您的实现上(从而通过代理).基本上,您需要将 @Scheduled 方法移动到另一个 bean.
  1. Demarcate the transaction programmatically as you are doing in your 'dirty' solution (you don't need the annotations is this case).
  2. Make sure that your @Scheduled method makes its call to dao.update(xxx); via the Service interface, not directly on your implementation (thereby going through the proxy). Basically you need to move the @Scheduled method to another bean.

我希望这足够清楚!

这篇关于Spring3 的 @Transactional @Scheduled 没有提交给 DB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆