在Hibernate中使用@Synchronize有什么用处

时间:2014-08-10 06:48:26

标签: java hibernate

根据Hibernate documentaion

  

Hibernate的视图和基表之间没有区别   映射。这在数据库级别是透明的,尽管有些DBMS   不正确支持视图,尤其是更新时。有时你   想要使用视图,但不能在数据库中创建一个视图(即   使用遗留架构)。在这种情况下,您可以映射一个不可变的和   使用的给定SQL子选择表达式的只读实体   @ org.hibernate.annotations.Subselect:

@Entity
@Subselect("select item.name, max(bid.amount), count(*) "
        + "from item "
        + "join bid on bid.item_id = item.id "
        + "group by item.name")
@Synchronize( {"item", "bid"} ) //tables impacted
public class Summary {
    @Id
    public String getId() { return id; }
    ...
}
  

声明表以同步此实体,确保这样做   自动刷新正确发生,并查询派生的   实体不返回陈旧数据。它可以作为   一个属性和一个嵌套的映射元素。

我不清楚这里给出的同步注释的声明。自动刷新有什么问题?这里派生的实体是什么?为什么我们会得到过时的数据?同步注释如何解决此问题。

有人可以帮助我理解这一点。

1 个答案:

答案 0 :(得分:17)

Hibernate实体在内存中保持持久状态。对这些实体的任何更改都会自动保持对数据库的持久性。但是每次更改实体字段时都不会更新数据库。它是在 flush 时完成的:Hibernate决定它必须使内存中的更改持久化,从而执行适当的insert,update和delete语句,以便数据库状态与in匹配 - 记忆状态。

什么时候发生?

    交易提交前
  • 在会话中明确呼叫flush()
  • 执行对修改实体的查询时

让我们关注第三项。假设您有一个Order实体,映射到订单表。假设您已按ID加载订单并修改其金额。修改仅在内存中。现在执行以下查询:

select sum(o.amount) from Order o

显然,此查询的结果取决于修改后的实体的新数量。在执行查询之前,Hibernate会检测到这一点并刷新对Order实体的更改,以确保查询返回正确的结果。如果查询已经

select c from Customer c where c.name = 'John'

在执行查询之前,Hibernate不会刷新对Order实体的更改,因为它的结果并不依赖于订单金额的新值:订单表不参与此查询。

现在问你的问题:既然Hibernate没有@Table注释来知道摘要映射到哪个表,那么在它之前它不应该知道它应该自动刷新的时间。执行涉及Summary实体的查询。同步注释允许告知Hibernate:此实体从项目和投标表中获取数据,因此如果对Summary实体执行查询,请确保在执行查询之前刷新对bid和items表的更改。