我有一个实体调用公司,另一个实体调用令牌。
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()中的过滤逻辑不合适。通过权限过滤逻辑不应该应用于实体级别。但由于目前有很多地方使用这种方法,如果我改变这个实体级别,那么会影响其他人,如果我也改变其他地方,它将需要重新测试整个应用程序。
因此,我试图找到一个更好的方法。
答案 0 :(得分:1)
您真正想要的是阻止Hibernate自动flushing
。
请参阅hibernate docs:
刷新是同步底层持久性的过程 持久存在的商店。
此问题的解决方案是通过设置FlushMode
将FlushMode.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);
}