java - 如何测试LazyInitializationException?

标签 java hibernate spring-transactions spring-test

我有一些代码(在生产中):

  • 在一个线程中,使用数据库中的数据填充缓存
  • 在另一个线程中,从缓存中获取数据,并开始迭代其属性。

这引发了LazyInitializationException

虽然我知道如何解决该问题,但我想对此进行测试。但是我不知道如何在测试的正确部分重新创建异常。

我必须用一些测试数据填充数据库,因此我的测试用@Transactional注释。如果不这样做会导致设置失败...您猜对了...LazyInitializationException

这是我当前的测试:

@Transactional
public class UpdateCachedMarketPricingActionTest extends AbstractIntegrationTest {

    @Autowired
    private UpdateCachedMarketPricingAction action;

    @Autowired
    private PopulateMarketCachesTask populateMarketCachesTask;

    @Test @SneakyThrows
    public void updatesCachedValues()
    {

        // Populate the cache from a different thread, as this is how it happens in real life
        Thread updater = new Thread(new Runnable() {
            @Override
            public void run() {
                populateMarketCachesTask.populateCaches();
            }
        });
        updater.start();
        updater.join();

             updateMessage = {...} //ommitted 

        action.processInstrumentUpdate(updateMessage);
    }

因此,我在一个单独的线程中启动缓存,尝试将其移出当前的 @Transaction 范围。此外,我还在缓存底漆内调用 entityManager.detatch(entity),以尝试确保缓存中存在的实体无法延迟加载其集合。

但是,测试通过了...没有抛出异常。

如何强制让实体进入某种状态,当我下次尝试迭代它的集合时,它将抛出 LazyInitializationException

最佳答案

您需要确保每个操作的事务都已提交,并且彼此独立。使用@Tranactional注释您的测试方法或测试类会使当前测试事务保持打开状态,然后在执行整个测试后将其回滚。

因此,一种选择是执行以下操作:

@Autowired
private PlatformTransactionManager transactionManager;


@Test
public void example() {
    new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {

        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            // add your code here...
        }
    });
}

您可以在其自己的回调中调用第一个操作,然后在不同的回调中调用第二个操作。然后,当您在回调后访问 Hibernate 或 JPA 实体时,这些实体将不再附加到当前工作单元(例如 Hibernate Session)。因此,此时访问惰性集合或字段将导致 LazyInitializationException

问候,

山姆

附:请注意,这种技术自然会将更改提交到您的数据库。因此,如果您需要清理修改后的状态,请考虑在 @AfterTransaction 方法中手动执行此操作。

关于java - 如何测试LazyInitializationException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17122955/

相关文章:

java - 事务未回滚

java - 链表和 jFrames

java - MongoDB/Java : Inserting Document in Sub-Document

Java 内存模型 - 令人惊讶的行为

java - 如何从运行在服务器外部(Web 应用程序)的 Spring hibernate 项目中使用 JBoss AS7 JNDI 数据源?

java - 当存在多个数据源时Spring动态事务管理器

java - WebResource 多部分发布请求

java - 为什么 @ManytoOne 或 @OnetoMany 在 Spring Boot 中产生问题

java - 当对象不在持久性上下文中时,Hibernate 合并不查询数据库

java - 如果我的值存储在线程安全映射中,该值是否需要是 ThreadLocal?