有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在hibernate中避免脏检查

我有一个实体呼叫公司和另一个实体呼叫令牌

1公司将有许多代币

因此,在我的公司实体中,我将有如下内容:

 @OneToMany(mappedBy = "companyId")
 public Set< Token > getTokens() {
    return tokens;
 }

但是,我在返回过程中会有一些逻辑,它会在返回之前更改令牌列表,如下所示:

@OneToMany(mappedBy = "companyId")
 public Set< Token > getTokens() {
    tokens.remove( token );
    return tokens;
 }

由于我更改了令牌列表中的值,因此,每次使用hibernate从db中选择company对象时,company表都会自动更新

根据我的理解,这是一种hibernate脏检查行为。所以,当Hibernate检测到有什么变化时,它将对数据库进行更新

有什么办法可以避免这种情况吗?例如,可能只调用现有的hibernate函数,这样hibernate就会知道令牌列表是脏的,并且不会进行更新

是的,我知道getTokens()中的过滤逻辑不合适。正确地说,过滤逻辑不应应用于实体级别。但由于目前有很多地方使用这种方法,如果我在这个实体级别进行更改,那么会影响其他地方,如果我也更改了其他地方,则需要重新测试整个应用程序

因此,我试图找到一个更好的方法


共 (1) 个答案

  1. # 1 楼答案

    你真正想要的是防止Hibernate自动flushing

    hibernate docs

    Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.

    这个问题的解决方案是通过设置FlushMode.MANUAL,将FlushMode的默认配置从自动更改为手动。这样,脏检查机制将停止导致上述同步

    尽管Session只在应用程序显式调用Session.flush()时才会刷新,如hibernate documentation中所述

    这里必须提到的是,如果你遵循建议的解决方案,你需要支付显式冲洗的费用,这意味着你需要显式冲洗 每次要提交数据库中的内容时,都要调用Session.flush()方法

    阅读here一些关于FlushMode的有用材料,如hibernate文档中的官方记录

    更新
    此解决方案适用于会话,因此如果只想将其应用于特定实体,则应尝试创建两种方法。一个用于将其设置为手动,另一个用于返回默认自动。通过这种方式,您将在手动设置后更改值,以防止刷新,然后将其设置回默认值,以免影响其他实体
    下面的实施可能会有所帮助:

    @Autowired
    private SessionFactory sessionFactory;
    
    
    @OneToMany(mappedBy = "companyId")
     public Set< Token > getTokens() {
        setFlushModeManual();
        tokens.remove( token );
        setFlushModeAuto();
        return tokens;
     }
    
    private void setFlushModeManual() {
        sessionFactory.getCurrentSession().setFlushMode(FlushMode.MANUAL);
    }
    
    private void setFlushModeAuto() {
        sessionFactory.getCurrentSession().setFlushMode(FlushMode.AUTO);
    }