我有两种方法。
@Service
@Transactional
public class MyService {
void myMethod() {
Entity e1 = dao.get(1);
e1.setName("NEW ENTITY NAME");
save(e1);
}
void save(Entity e) {
Entity oldEntity = dao.get(1);
oldEntity.getName().equals(e.getName()) // TRUE. Why?
}
}
但是在方法save
中,实体没有区别,即旧实体和更新实体都具有相同的字段值("NEW ENTITY NAME"
)。 Spring中的事务配置正确,默认传播是Propagation.REQUIRED
。
答案 0 :(得分:2)
同样见answer,这实际上是正常行为。第一个dao.get(1)检索具有数据库密钥1的实体,并且附加到会话。
执行第二个dao.get(1)时,会话仍然打开,因此Hibernate不会再次查询数据库,而是返回已经附加到会话的引用。
从Hibernate的角度来看,这个表只有一个数据库对象,键1,并且它已经拥有对它的最新内存版本的引用,所以Hibernate也可以返回它并备用一个查询。
为了比较内存中的持久对象与它的数据库版本,一种方法是首先加载对象并在调用对象上的setter之前进行比较。
另一种方法是首先使用session.evict()从会话中分离对象,然后从数据库加载对象。
这将确保数据的数据库版本被加载到会话中。然后可以在现在分离的被驱逐对象和新加载的对象之间进行比较。
如果您不想使用较新的数据替换数据库版本,请在被驱逐的对象上调用session.merge()。
答案 1 :(得分:1)
如果我没记错的话,Hibernate在会话级别有一个缓存系统,如果检索到某个实体,它将被缓存并返回同一个Session内同一实体的任何请求。因此,您要比较同一个对象。您可以通过
确认oldEntity == e
答案 2 :(得分:0)
如果要使用较新的数据替换数据库版本,请在被驱逐的对象上调用session.merge()