【问题标题】:How to link JPA persistence context with single database transaction如何将 JPA 持久性上下文与单个数据库事务链接
【发布时间】:2016-04-10 10:47:27
【问题描述】:

最新的带有 JPA 和 Hibernate 的 Spring Boot:我正在努力理解事务、持久性上下文和休眠会话之间的关系,而且我无法轻易避免可怕的无会话延迟初始化问题。

我在一个事务中更新一组对象,然后我想遍历这些对象,在一个单独的事务中处理它们——看起来很简单。

public void control() {
    List<> entities = getEntitiesToProcess();
    for (Entity entity : entities) {
        processEntity(entity.getId());
    }
}

@Transactional(value=TxType.REQUIRES_NEW)
public List<Entity> getEntitiesToProcess() {
    List<Entity> entities = entityRepository.findAll();
    for (Entity entity : entities) {
        // Update a few properties
    }
    return entities;
}

@Transactional(value=TxType.REQUIRES_NEW)
public void processEntity(String id) {
    Entity entity = entityRepository.getOne(id);
    entity.getLazyInitialisedListOfObjects(); // throws LazyInitializationException: could not initialize proxy - no Session
}

但是,我遇到了一个问题,因为(我认为)两个事务都使用了相同的休眠会话。当我在第二个事务中调用 entityRepository.getOne(id) 时,我可以在调试器中看到我返回的对象与第一个事务中 findAll() 返回的对象完全相同,而没有数据库访问。如果我理解正确,是休眠缓存在做这个吗?如果我随后在我的对象上调用需要延迟评估的方法,则会收到“无会话”错误。我认为缓存和会话是链接的,所以这是我的第一个困惑。

如果我删除所有的@Transactional 注释,或者如果我在控制方法上放置一个@Transactional,它都运行良好,但是数据库提交直到控制方法完成才完成,这显然不是我想要的。

所以,我有几个问题:

  1. 如何使休眠会话与我的事务范围保持一致?
  2. 使用 JPA 和声明式事务管理在循环中执行分离事务的良好模式是什么?

我想保留声明式风格(即没有 xml),并且不想做任何特定于 Hibernate 的事情。

任何帮助表示赞赏!

谢谢

马库斯

【问题讨论】:

    标签: spring hibernate jpa transactions spring-data-jpa


    【解决方案1】:

    Spring 围绕您的服务类创建一个代理,这意味着 @Transactional 注释仅在通过代理(您已注入此服务的位置)调用带注释的方法时应用。

    您正在从control() 内部调用getEntitiesToProcess() 和processEntity(),这意味着这些调用不通过代理,而是具有control() 方法的事务范围(如果您不调用@987654326 @来自同一类中的另一个方法)。

    为了让@Transactional 申请,你需要做这样的事情

    @Autowired
    private ApplicationContext applicationContext;
    
    public void control() {
        MyService myService = applicationContext.getBean(MyService.class);
        List<> entities = myService.getEntitiesToProcess();
        for (Entity entity : entities) {
            myService.processEntity(entity.getId());
        }
    }
    

    【讨论】:

    • Grrgh。多么令人沮丧!我完全看错了地方,虽然我确实知道所有关于代理和事务拦截器的信息,但我被会话消息分心了,我没有注意到事务没有正常工作!谢谢,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2017-02-17
    • 2015-03-03
    • 2018-02-25
    • 2011-04-22
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多