在编写“非规范化”集合时,我遇到了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)。
我的应用程序会编写电影和演员......稍后,它会通过编写信用点将它们链接在一起。写入Credit时,我只填写roleName,movieId和actorId字段,我不提供Movie和Actor对象。
使用NONSTRICT_READ_WRITE缓存,我可以读回该Credit对象,它将包含引用的Movie和Actor对象。
使用READ_WRITE缓存,回读Credit将返回带有空Movie和Actor字段的Credit。如果我清除了hibernate缓存,那么回读那个Credit然后按预期包含Movie和Actor对象。这也是TRANSACTIONAL缓存的行为(但当然不是使用NONE缓存)。
因此,当使用READ_WRITE缓存时,hibernate似乎将Credit插入到具有空Actor和Movie字段的二级缓存中。有没有办法防止这种情况发生,并始终从数据库中读取以获取这些连接的字段?我尝试使用CacheConcurrencyStrategy.NONE注释字段,但这不起作用。
答案 0 :(得分:0)
我认为你可能偶然发现了一个hibernate bug,因为你的怪异映射(至少是非标准映射)。没有真正的理由让两个字段一个带有id,一个带有实体。
您可以使用session.load
将ID转换为实体引用 - 这只是创建代理,不会从数据库加载数据。
如果你摆脱movieId和actorId字段并删除movie / actor字段中的insertable / updatable false,它应该与READ_WRITE
或NON_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表)并从中重建对象。所以你断言它将对象存储在缓存中并且没有更新它是不正确的。还有其他事情要发生。
READ_WRITE
和NON_STRICT_READ_WRITE
之间的主要区别在于,在READ_WRITE的情况下,缓存中的条目将在更新时被锁定,并且不会在NON_STRICT_READ_WRITE中被锁定。这只会影响您同时在多个线程中更新此实体。