【问题标题】:why hibernate update DB after evict为什么在驱逐后休眠更新数据库
【发布时间】:2016-06-30 03:25:06
【问题描述】:

我有两个关联的实体:

@Entity
@DynamicUpdate(true)
public class DreamTaskInfo {  
  private DreamInfo dreamInfo;  
  @ManyToOne
  @JoinColumn(name = "DREAM_INFO_ID", nullable = false)
  public DreamInfo getDreamInfo() {
      return dreamInfo;
  }  
 ...  
}  

@Entity
@DynamicUpdate(true)
public class DreamInfo {
    private Set<DreamTaskInfo> dreamTasks = new LinkedHashSet<>();
    @OneToMany(mappedBy = "dreamInfo",cascade = CascadeType.ALL,   fetch = FetchType.EAGER)
   @OrderBy("remindTime")
   public Set<DreamTaskInfo> getDreamTasks() {
     return dreamTasks;
  }
  ...
}  

我想将数据库中的 DreamTaskInfo 数据用于只读用途,所以我这样做:

DreamTaskInfo task = this.get(id);//query from db
getSession().evict(task);//getSession().contains(task)==false

但我发现 Hibernate 在刷新时总是在此任务上执行更新 sql。 最后,我使用 getSession().clear() 而不是 evict 并且它有效。 也许急切地获取或关联会导致会话中的某些内容? 其实我并没有手动修改任何东西并自动休眠更新,所以它与这个question无关。

【问题讨论】:

标签: java hibernate


【解决方案1】:

您必须在调用 evict() 之前刷新会话。然后你不会看到在 evict() 之后运行更新查询。

解决方案:

DreamTaskInfo task = this.get(id);//query from db
getSession().flush();// to make sure atomicity of session is maintained
getSession().evict(task);//getSession().contains(task)==false

在您从数据库中获取对象后可能会发生一些变化,这就是 hibernate 将运行更新查询的原因。

会话被设计为基于工作单元的接口,这是有充分理由的——如果没有此功能,事务语义将是一场灾难。如果您需要刷新单个实体而不刷新属于同一会话的其他实体,则需要重新考虑您的工作单元。

【讨论】:

  • 我忘了说我试过这种方法,但是不行。
  • "你从数据库中获取对象后可能会发生一些变化,"我也有同样的想法,但是我使用junit来测试这个方法并且没有修改任何东西,所以不知道这是怎么回事完全正确。
  • 即使你没有修改任何东西。您仍然需要为会话调用flush。但是根据您之前的评论,我想您已经尝试过了。我会再次检查并回复您。
  • @yuxh 你的解决方案是什么
  • @Gaurava,我还没弄清楚原因,暂时使用getSession().clear()。
猜你喜欢
  • 2011-12-29
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
  • 2017-07-11
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
相关资源
最近更新 更多