0

在编写“非规范化”集合时,我遇到了 NONSTRICT_READ_WRITE 和 READ_WRITE CacheConcurrencyStrategy 之间的差异......我的想法是我有一个连接表建模为实体,但它还包含指向它连接的表的只读链接。

我的实体,大致:

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Actor {
    @Id
    Integer id;
    @Column
    String name;
}

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Movie {
    @Id
    Integer id;
    @Column
    String title;
}

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Credit {
    @Column
    String roleName;

    @ManyToOne(targetEntity = Movie.class, optional = true)
    @JoinColumn(name = "movie_id", insertable = false, updatable = false)
    @NotFound(action = NotFoundAction.IGNORE)
    Movie movie;

    @Column(name = "movie_id")
    Long movieId;

    @ManyToOne(targetEntity = Actor.class, optional = true)
    @JoinColumn(name = "actor_id", insertable = false, updatable = false)
    @NotFound(action = NotFoundAction.IGNORE)
    Actor actor;

    @Column(name = "actor_id")
    Long actorId;
}

启用二级对象缓存(使用 ehcache)。

我的应用程序编写 Movies 和 Actors... 一段时间后,它通过编写 Credit 将它们链接在一起。在写 Credit 的时候,我只填写了 roleName、movieId 和 actorId 字段,我没有提供 Movie 和 Actor 对象。

使用 NONSTRICT_READ_WRITE 缓存,我可以读回 Credit 对象,它将包含引用的 Movie 和 Actor 对象。

使用 READ_WRITE 缓存,读回 Credit 将返回一个具有空 Movie 和 Actor 字段的 Credit。如果我清除休眠缓存,则读取该 Credit 然后按预期包含 Movie 和 Actor 对象。这也是 TRANSACTIONAL 缓存的行为(但当然不是 NONE 缓存)。

因此,当使用 READ_WRITE 缓存时,似乎休眠将 Credit 插入到具有空 Actor 和 Movie 字段的 2 级缓存中。有没有办法防止这种情况发生并始终从数据库中读取以取回这些连接字段?我尝试使用 CacheConcurrencyStrategy.NONE 仅注释字段,但这不起作用。

4

1 回答 1

0

我想你可能因为你奇怪的映射(至少是非标准映射)而偶然发现了一个休眠错误。没有真正的理由有两个字段,一个带有 id,一个带有实体。

您可以使用 - 将 id 转换为实体引用session.load,它只是创建一个代理,不会从 DB 加载数据。

如果您摆脱了 movieId 和 actorId 字段并删除了电影/演员字段上的可插入/可更新的 false ,则无论READ_WRITENON_STRICT_READ_WRITE

Credit c = new Credit()
Movie m = session.load(movieId);
Actor a = session.load(actorId);
c.setMovie(m);
c.setActor(a);
session.save(c);

Hibernate 不会将完整的对象保存在二级缓存中。我将它存储为扁平形式(水合 - 更像是 db 表)并从中重建对象。因此,您断言它在缓存中存储了具有 null 的对象并且没有更新它是不正确的。还有其他事情正在发生。

READ_WRITE和之间的主要区别在于NON_STRICT_READ_WRITE,缓存中的条目将在 READ_WRITE 的情况下在更新时被锁定,而在 NON_STRICT_READ_WRITE 中不会被锁定。仅当您同时在多个线程中更新此实体时,这才会产生影响。

于 2012-09-08T07:32:50.287 回答