9

Spring3 の @Scheduled を試すのはこれが初めてですが、DB にコミットできないことがわかりました。これは私のコードです:

@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);
  }
}

私はそれが動作するはずだと思います.1時間ごとに起動し、DBからxxxをロードするのを見ることができますが、データはDBにコミットされていません.

tx:annotation-driven春の 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" />

誰かが私がここで見逃したことを教えてもらえますか?

私は1つの「汚い」解決策を持っています:

@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 が挿入されていない(そして開かれていない) のはなぜでしょうか?

どうもありがとう !

4

3 に答える 3

19

あなたはおそらくこれを理解しているか、先に進んでいるでしょう(私はそう願っています)が、他の人の利益のために:

@Transactionalアノテーションは、' ' も実装する動的プロキシで元の Bean をラップするように Spring に指示しServiceImplますService(デフォルトでは、Spring は実装ではなくインターフェースをプロキシします)。hourly() このプロキシは、プロキシを呼び出すと、トランザクションの作成とコミット/ロールバックを透過的に処理します。ただし、実装を直接呼び出すとhourly()(上記で発生していることです)、プロキシはバイパスされるため、トランザクションは発生しません。

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

解決策は次のいずれかです

  1. 「汚い」ソリューションで行っているように、プログラムでトランザクションを区別します (この場合、注釈は必要ありません)。
  2. @Scheduled メソッドがdao.update(xxx);、実装で直接ではなく、Service インターフェースを介して呼び出しを行うことを確認してください (したがって、プロキシを経由します)。@Scheduled基本的に、メソッドを別の Beanに移動する必要があります。

それが十分に明確であることを願っています!

于 2012-10-18T14:53:31.917 に答える
0

アノテーション駆動型サポートを使用すると、そのコンテキスト内で作成されたクラスでのみ機能します。私の賭けは、ServiceImpl がトランザクション マネージャーと同じコンテキストで (直接または注釈スキャンによって) 作成されないことです。

于 2011-03-26T17:19:01.543 に答える
0

私は同じ問題を抱えていましたが、それに時間を費やした後、null 値をチェックしない無関係なコードで dao.update() 呼び出しの後に例外が発生したことに気付きました。そのため、単純にトランザクションが中断されました。spring (いくつかの catch ブロック) によって適切に処理されているため、stackTrace の印刷はありませんでした。私はそれにしばらく費やしました。そのため、トランザクションメソッドが最後まで完了することを確認してください。それが誰かを助けることを願っています。

ヨシ・レフ

于 2015-04-26T16:48:28.913 に答える