20

新しいスレッドでJPAを使用してデータベースにデータを保存する簡単な解決策はありますか?

私のSpringベースのWebアプリケーションを使用すると、ユーザーはスケジュールされたタスクを管理できます。実行時に、事前定義されたタスクの新しいインスタンスを作成して開始できます。私は春のTaskSchedulerを使用しており、すべてがうまく機能しています。

しかし、実行されたすべてのタスクのブール結果をデータベースに保存する必要があります。これどうやってするの?

編集:質問を一般化する必要があります:タスクから@Serviceクラスのメソッドを呼び出す必要があります。データベースに保存する前に、タスクの結果を「処理」する必要があるためです。

編集2:私の問題のあるコードの簡略版がここにあります。saveTaskResult()がスケジューラーから呼び出されると、メッセージは出力されますが、dbには何も保存されません。しかし、コントローラーからsaveTaskResult()を呼び出すと、レコードはデータベースに正しく保存されます。

@Service
public class DemoService {

    @Autowired
    private TaskResultDao taskResultDao;

    @Autowired
    private TaskScheduler scheduler;

    public void scheduleNewTask() {
        scheduler.scheduleWithFixedDelay(new Runnable() {

            public void run() {
                // do some action here
                saveTaskResult(new TaskResult("result"));
            }

        }, 1000L);
    }

    @Transactional
    public void saveTaskResult(TaskResult result) {
        System.out.println("saving task result");
        taskResultDao.persist(result);
    }

}
4

3 に答える 3

34

コードの問題は、を呼び出すときにトランザクションが開始されることを期待していることですsaveTaskResult()。SpringはAOPを使用してトランザクションを開始および停止するため、これは発生しません。

Beanファクトリから、または依存性注入を介してトランザクションSpring Beanのインスタンスを取得する場合、実際に取得するのはBeanのプロキシです。このプロキシは、実際のメソッドを呼び出す前にトランザクションを開始し、メソッドが完了するとトランザクションをコミットまたはロールバックします。

この場合、トランザクションプロキシを経由せずに、Beanのローカルメソッドを呼び出します。saveTaskResult()メソッド(で注釈が付けられている@Transactional)を別のSpringBeanに入れます。この他のSpringBeanをDemoServiceに注入し、DemoServiceから他のSpring Beanを呼び出すと、すべてが正常になります。

于 2012-06-30T21:08:18.557 に答える
4

トランザクションはスレッドローカルストレージで保持されます。他のメソッドがアノテーション付き
のスレッドを実行している場合。 デフォルトはに設定されており、これは、別のスレッドから注釈が付けられたメソッドを実行すると、新しいトランザクションが発生することを意味します(このスレッドのスレッドローカルストレージにトランザクションが保持されていないため)。@Transactional
REQUIRED@Transacitonal

于 2012-06-30T17:36:36.597 に答える
0

別のオプション(@Transactionalメソッドを使用して個別のSpring Beanを作成する以外)は、を使用してトランザクションを手動で設定することTransactionTemplateです。

final TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
   taskExecutor.execute(new Runnable() {
        @Override
        public void run() {
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                   dao.update(object);
                }
            });
        }
    });  
于 2021-09-22T10:24:55.100 に答える