我有一个实体调用公司,另一个实体调用 token 。
1家公司将拥有许多代币。
因此,在我的公司实体中,我将执行以下操作:
@OneToMany(mappedBy = "companyId")
public Set< Token > getTokens() {
return tokens;
}
但是,我在返回过程中会有一些逻辑,它会在返回之前更改 token 列表,如下所示:
@OneToMany(mappedBy = "companyId")
public Set< Token > getTokens() {
tokens.remove( token );
return tokens;
}
由于我更改了 token 列表中的值,因此,每次我使用 hibernate 从数据库中选择公司对象时,公司表都会自动更新。
根据我的理解,这是hibernate脏检查的行为。所以当Hibernate检测到有什么变化时,它就会对数据库进行更新。
有什么办法可以避免这种情况吗?例如,也许只是调用现有的 hibernate 函数,这样 hibernate 就会知道 token 列表是脏的,并且不会进行更新。
是的,我知道 getTokens() 中的过滤逻辑不合适。正确地说,过滤逻辑不应应用于实体级别。但由于目前有很多地方使用这种方法,如果我在这个实体级别进行更改,那么将会影响其他地方,如果我也更改其他地方,则需要再次重新测试整个应用程序。
因此我正在尝试寻找更好的方法。
最佳答案
您真正想要的是阻止 Hibernate 自动刷新
。
参见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 Hibernate 文档中正式记录了一些有关 FlushMode 的有用 Material 。
更新:
此解决方案适用于 session ,因此如果您只想将此解决方案应用于特定实体,您应该尝试创建两个方法。一种用于将其设置为“手动”,一种用于返回默认“自动”。这样,您将在手动设置后更改您的值以防止刷新,随后您将其设置回默认值,以免影响其他实体。
也许下面的实现会有所帮助:
@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);
}
关于java - 如何避免 hibernate 中的脏检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47343057/