提问者:小点点

Hibernate Envers:检索具有集合属性的实体的正确版本


我有两个被审计的实体,A和B。实体A持有实体B的集合(注释为一对多关系)。当将A的新实例插入数据库时,A和B的所有行都在同一个修订版(假设修订版1)。然后,A上有一个更新,它只影响实体B的实例。所以在更新之后,实体A仍然处于修订版1,而B的实体处于修订版2(包括审计表中的MOD条目)。在修订版3中,实体A被删除。因为实体B的集合用@Cascade注释,所以属于A的实体B也被删除。

在这种情况下,如何使用Envers创建一个审计查询,该查询获取实体A的实例,其中包含修订2的更新实体B?当我查询实体A的所有修订时,我要么获取A的已删除实体,其中不包含B的实体(修订3),要么获取修订1的A,其中包含修订1的B实体。

使用Hibernate 3.6,如果有帮助的话。


共3个答案

匿名用户

我解决了一个类似的问题,在我的等效于你的A实体上添加了一个隐藏的最后更新日期字段。

@Entity
public class A {
    private Date lastModified;
    @OneToMany(mappedBy = "a", cascade = CascadeType.ALL )
    private List<B> blist;
    public void touch(){
        lastModified=new Date();
    }
}

然后在相关实体(比如你B字段)中,我添加了以下内容:

public class B {
    @ManyToOne
    private A a; 

    @PreUpdate
    public void ensureParentUpdated(){
        if(a!=null){
            a.touch();
        }
    }
}

这可确保在将修订添加到B时将修订添加到A,即使它需要许多实体中的自定义代码。

在您的情况下,这将确保A的历史记录实际上包含B的修订,这样您只需要一个查询即可获取整个A、B图的所有修订

匿名用户

如果您在修订版2中读取实体A,您将获得正确的数据。

目前无法获得实体或相关实体更改的修订列表(就像您的情况一样-rev 2仅在B中更改,而不是在a中)。

匿名用户

在Hibernate中,我们可以通过指定懒惰来控制子级的加载。因此,您需要将以下行添加到Hibernate配置中的类定义中,以便它在读/写情况下加载所有关联。

<cache usage="read-write"/>

如果您标记了CacheMode. REFRESH,那么它会将项目写入二级缓存。不要从二级缓存中读取。

如果您在加载父级时没有问题,您可以切换为懒惰,这将返回更新的信息。