Spring3的@Transactional @Scheduled是否未提交给DB? [英] Spring3 's @Transactional @Scheduled not committed to DB?

查看:503
本文介绍了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 ?

我有一个''解决方案:

I have one 'dirty' solution :

@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-use-spring-spring/

解决方案是

  1. 像在脏"解决方案中一样,以编程方式对事务进行划分(在这种情况下,不需要注释).
  2. 请确保您的@Scheduled方法通过Service接口而不是直接在您的实现上(因此通过代理)对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天全站免登陆