Hibernate一级缓存 – 是否同步?
我知道Session
是Hibernate使用的第一级缓存,一旦我们从session
检索实体,后续对具有相同标识符的同一实体的 get调用将从session
而不是DB中获取,直到session
为止。 打开 。
话虽如此,我对hibernate如何将第一级缓存与DB同步有疑问? 请考虑以下情形
//Lets say I have created the session Session s1 = sessionFactory.getSession(); User u1 = s1.get(User.class, 1); //Getting User with ID=1 //s1 is not yet closed //Lets say I create some other session Session s2 = sessionFactory.getSession(); User u2 = s2.get(User.class, 1); //Getting User with ID=1 u2.setName("Abc"); // Changed a field s2.save(u2); // Saved the changes to DB s2.close(); //Closed the 2nd session //Now when I once again retrieve User with ID=1 from s1, will I get updated User? User u3 = s1.get(User.class, 1);// Here as per my understanding cache is used
所以我的问题是
- 由于
u3
是从1级缓存中获取的,u3
是否有更新值? - 如果有人直接更新数据库并在会话打开时修改用户对象,会话是否与数据库同步?
在此post中提前感谢您的时间和精力
不,除非您明确请求,否则Hibernate不会执行任何操作来将会话缓存中的实体状态与数据库同步。
通常这不是问题,因为活动工作通常发生在事务中,并且事务内的操作不应该看到其他并发事务所做的更改(但细节依赖于隔离级别)。 因此,在这种情况下,Hibernate的行为补充了事务隔离的典型语义。
还可能存在需要明确同步实体状态以反映在同一事务内进行的更改的情况。 它可能是由批量更新查询或数据库触发器的执行引起的。 在这种情况下,您需要通过调用refresh()
显式请求此类同步。
您需要使用u1
作为参数在s1
上调用Session.evict(Object)
以获得新的查找。 或者,对于这种情况,您也可以在s1
上调用Session.clear()
以获得相同的效果。 您也可以调用Session.refresh(Object object)
来刷新u1
的状态。
请注意,事务可能需要一段不确定的时间(通常不会很长),以便其他客户端在提交后可以看到。 使用不同连接的其他会话可能无法立即看到更新。
第一级(会话级)缓存确保一个事务加载的持久实例的状态与其他事务所做的更改隔离。
因此,当您在第一个事务中调用s1.get(User.class, 1)
时, s2
在不同事务(T2)中所做的更改是不可见的,因为这次Hibernate将从会话级缓存s1
获取User
。