【问题标题】:@Transactional(readOnly=true) vs @QueryHints@Transactional(readOnly=true) 与 @QueryHints
【发布时间】:2017-06-06 11:08:44
【问题描述】:

我有一个 Spring Data JPA 存储库,其方法如下:

//@QueryHints({ @QueryHint(name = "org.hibernate.readOnly", value = "true") })
@Transactional(readOnly = true)
Account findByUsername(String username);

当Account 变脏时,hibernate 会在调用此方法时尝试刷新它——这是我不想要的。我认为将其设置为 @Transactional(readOnly = true) 可以对此有所帮助,但事实并非如此。有趣的是使用@QueryHints 和具体的休眠提示确实 工作。现在我想知道为什么。 @Transactional(readOnly=true)不应该有同样的效果吗?

【问题讨论】:

    标签: java hibernate transactions spring-data repository


    【解决方案1】:

    如果我们想坚持非供应商特定的方式,那么我会尝试:

    选项 1

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    Account findByUsername(String username);
    

    这里我们确实在任何事务之外运行查询,因此不会影响持久性上下文的现有状态。好好想想这种情况是否适合这种配置。

    选项 2

    我假设您在查询用户之前正在对当前事务进行一些其他修改。我建议然后将刷新模式设置为提交给您的查询(或实体管理器):

    EntityManager em;
    Account findByUsername(String username){
       em.setFlushMode(FlushModeType.COMMIT);
    
      // perform the query
    }
    

    或

    EntityManager em;
    Account findByUsername(String username){
      Query query = em.createQuery(..); 
      query.setFlushMode(FlushModeType.COMMIT);
    
      // perform the query
    }
    

    COMMIT 刷新模式告诉持久化提供者查询不会与持久化上下文中更改的数据重叠,因此它不需要做任何事情来获得正确的结果。

    在查询本身上设置刷新模式是一种可取的方法。

    更新:选项 3

    作为最后的手段,您可以在核心配置本身上进行设置:

    <property name="org.hibernate.flushMode" value="COMMIT"/>
    

    现在这是在您无法访问实体管理器并手动设置刷新模式时使用。

    【讨论】:

    • 选项 2b 听起来很有趣,但我使用的是 Spring Data Repositories,其中 Spring Data 会根据接口方法名称自动生成查询。所以我没有得到实际的查询。因此,我认为我可以通过注释添加该提示,而 Spring 会为我选择它并将其设置在它生成的查询中。当然,我可以构建自己的 Repository Impl 并在那里做这些事情,但我很懒 :)。
    • 我明白你的意思,但易于自动配置带来了需要处理的自定义案例的痛苦。工具无法考虑您想做的所有事情。想象一下……没有人需要开发人员了……
    • 我又想到了一个选项
    • 是的,这将改变所有交易。我只是想在特殊情况下拥有它。同时,我只是通过在调用之前不更改对象来避免刷新。所以我会接受你的回答,它提供了一些不错的选择!
    • 太棒了!很高兴它给了你一些价值。
    猜你喜欢
    • 2020-05-16
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 2021-04-23
    • 2020-08-15
    相关资源
    最近更新 更多