如何将Spring事务传播到另一个线程?
也许,我做错了什么,但对于以下情况我找不到好的出路。
我想对一个使用 Spring Batch 执行作业的服务进行单元测试。这些作业通过预先配置的 AsyncTaskExecutor
在单独的线程中执行。在我的单元测试中,我想:
- 创建一些域对象并通过 DAO 保存它们
- 调用服务方法来启动作业
- 等待作业完成
- 使用 DAO 检索域对象并检查它们的状态
显然,以上所有内容都应该在一笔交易,但不幸的是,交易不会传播到新线程(我了解其背后的原理)。
我想到的想法:
- 在步骤 (1) 之后提交事务#1。不好,因为单元测试后应该回滚数据库状态。
- 在作业配置中使用
Isolation.READ_UNCOMMITTED
。但这需要两种不同的配置用于测试和生产。
Perhaps, I am doing something wrong, but I can't find a good way out for the following situation.
I would like to unit test a service that uses Spring Batch underneath to execute jobs. The jobs are executed via pre-configured AsyncTaskExecutor
in separate threads. In my unit test I would like to:
- Create few domain objects and persist them via DAO
- Invoke the service method to launch the job
- Wait until the job is completed
- Use DAO to retrieve domain objects and check their state
Obviously, all above should be executed within one transaction, but unfortunately, transactions are not propagated to new threads (I understand the rationale behind this).
Ideas that came to my mind:
- Commit the transaction#1 after step (1). Is not good, as the DB state should be rolled back after the unit test.
- Use
Isolation.READ_UNCOMMITTED
in job configuration. But this requires two different configurations for test and for production.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为最简单的解决方案是在测试执行期间使用 SyncTaskExecutor 配置 JobLauncher - 这样作业就在与测试相同的线程中执行并共享事务。
任务执行器配置可以移动到单独的 spring 配置 xml 文件中。它有两个版本 - 一个是在测试期间使用的 SyncTaskExecutor,另一个是用于生产运行的 AsyncTaskExecutor。
I think the simplest solution would be configure the JobLauncher with a SyncTaskExecutor during test execution - this way the job is executed in the same thread as the test and shares the transaction.
The task executor configuration can be moved to a separate spring configuration xml file. Have two versions of it - one with SyncTaskExecutor which is used during testing and the other AsyncTaskExecutor that is used for production runs.
尽管这不是您问题的真正解决方案,但我发现可以在工作线程内手动启动新事务。在某些情况下,这可能就足够了。
来源: Spring 程序化事务。
例子:
Although this is not a true solution to your question, I found it possible to start a new transaction inside a worker thread manually. In some cases this might be sufficient.
Source: Spring programmatic transactions.
Example:
如果您确实需要单独的配置,我建议您在配置中对隔离策略进行模板化,并从属性文件中获取其值,这样您就不会得到一组不同的 Spring 配置用于测试和生产。
但我同意使用与生产用途相同的政策是最好的。您的夹具数据有多大,如果有一个
setUp()
步骤会破坏并重建您的数据(可能是快照,如果数据很多的话),那么情况会有多糟糕不必依赖回滚?If you do want separate configurations, I'd recommend templating the isolation policy in your configuration and getting its value out of a property file so that you don't wind up with a divergent set of Spring configs for testing and prod.
But I agree that using the same policy production uses is best. How vast is your fixture data, and how bad would it be to have a
setUp()
step that blew away and rebuilt your data (maybe from a snapshot, if it's a lot of data) so that you don't have to rely on rollbacks?