@Synchronize在Hibernate中的用途是什么?

8
根据Hibernate文档,对于Hibernate映射,视图和基本表没有区别。虽然在数据库级别上透明,但某些DBMS不支持视图,特别是更新操作。有时您想使用视图,但无法在数据库中创建视图(即具有遗留架构)。在这种情况下,您可以使用@org.hibernate.annotations.Subselect将不可变且只读的实体映射到给定的SQL子选择表达式。
@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; }
    ...
}

声明要与此实体同步的表,确保自动刷新正确,并且针对派生实体的查询不会返回过期数据。Synchronize注释可作为属性和嵌套映射元素使用。我对这里提供的Synchronize注释陈述不够清楚。自动刷新存在什么问题?这里的派生实体是什么,我们为什么会得到过期数据?如何使用Synchronize注释解决这个问题,请有人帮助我理解。
1个回答

31

Hibernate的实体在内存中保存持久状态。对这些实体进行的任何更改都会自动地持久化到数据库中。但是每次更改实体字段时,数据库并不会立刻更新,而是在flush时刻才会执行相应的插入、更新和删除语句,以使数据库状态与内存状态匹配。

这个过程会在什么时候发生?

  • 在事务提交之前
  • 当你在session上显式调用flush()方法时
  • 当一个查询涉及到已修改的实体时

让我们着重看一下第三种情况。假设你有一个映射到订单表的Order实体,并且已通过ID加载了一个订单并修改了其金额。该修改仅存在于内存中。现在,你执行以下查询:

select sum(o.amount) from Order o

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

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

Hibernate在执行查询之前不会将更改刷新到订单实体中,因为其结果不取决于订单金额的新值:订单表与此查询无关。

现在回答您的问题:由于Hibernate没有@Table注释来知道Summary映射到哪个表,所以它不知道在执行涉及Summary实体的查询之前是否应该自动刷新。 Synchronize注释允许告诉Hibernate:此实体从item和bid表获取数据,因此如果针对Summary实体执行查询,请确保在执行查询之前刷新bid和item表的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接