如何避免在hibernate中进行脏检查

时间:2017-11-17 03:58:12

标签: java hibernate entity one-to-many mappedby

我有一个实体调用公司,另一个实体调用令牌。

1公司将有许多令牌。

所以在我的公司实体中,我会有类似的内容:

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

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

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

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

根据我的理解,这是hibernate脏检查的行为。因此,当Hibernate检测到它发生了某些变化时,它将对数据库进行更新。

有什么方法可以避免这种情况吗?例如,可能只是调用现有的hibernate函数,以便hibernate知道令牌列表是脏的,它不会做更新。

是的,我知道getTokens()中的过滤逻辑不合适。通过权限过滤逻辑不应该应用于实体级别。但由于目前有很多地方使用这种方法,如果我改变这个实体级别,那么会影响其他人,如果我也改变其他地方,它将需要重新测试整个应用程序。

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

1 个答案:

答案 0 :(得分:1)

您真正想要的是阻止Hibernate自动flushing

请参阅hibernate docs

  

刷新是同步底层持久性的过程   持久存在的商店。

此问题的解决方案是通过设置FlushModeFlushMode.MANUAL的默认配置从自动更改为手动。以这种方式,脏检查机制将停止引起上述同步。

虽然Session仅在应用程序显式调用Session.flush()时被刷新,如hibernate documentation中所述。

这里必须提到的是,如果你按照建议的解决方案,你需要支付明确刷新的价格,这意味着你需要明确 每次要在数据库上提交某些内容时调用Session.flush()方法。

阅读here一些有关FlushMode的有用资料,正如hibernate文档中正式记录的那样。

<强>更新
此解决方案适用于Session,因此如果您只想在特定实体上应用此解决方案,则应尝试创建两个方法。一个用于将其设置为MANUAL,另一个用于将其设置为默认AUTO。这样,您将在MANUAL设置后更改您的值以防止刷新,然后您将其设置回默认值,以免影响其他实体。
也许下面的实现会有所帮助:

@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);
}