0

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

1 公司将拥有许多代币。

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

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

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

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

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

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

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

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

因此,我试图在这方面找到更好的方法。

4

1 回答 1

2

你真正想要的是防止 Hibernate 从 auto flushing

请参阅休眠文档

刷新是将底层持久存储与内存中保存的持久状态同步的过程。

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

虽然Session只有在应用程序显式调用时才会刷新,Session.flush()休眠文档中所述。

这里必须提到的是,如果您遵循建议的解决方案,您需要支付显式刷新的代价,这意味着您Session.flush()每次想要在数据库上提交某些内容时都需要显式调用该方法。

在此处阅读一些有用的材料,这些材料与FlushModehibernate 文档中的正式文档有关。

更新
此解决方案适用于会话,因此如果您只想将其应用于特定实体,您应该尝试创建两种方法。一种用于将其设置为手动,一种用于恢复默认的自动。这样,您将在手动设置后更改您的值以防止刷新,随后您将其设置回默认值,以免影响其他实体。
也许下面的实现会有所帮助:

@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);
}
于 2017-11-17T09:09:09.503 回答