EntityEntry, EntityKey, Cache..Hibernate源码研究碎得(13)


如上篇结束时所言,本篇中着重研究upgradeLock这个方法.

 

进入方法后第一句就是这个requestedLockMode.greaterThan( entry.getLockMode())判断,若不成立,就马上退出此方法.

 

有些疑问的是EntityEntry类型的entry里getLockMode有什么意义?再往下追就是EntityEntry里的lockMode是什么时候什么情景下赋值的?


.......................


刚才用Eclipse里实际debug了一番,现在明白了些.


 1,那个LockMode所Lock的是缓存里的Entity,把数据从DB中取出并封装成Java中的对象后,先通过addEntity的方式以entityKey为Key,以实际的Entity为value放入到PersistenceContext中的Map类型的entitiesByKey里,(这也就是SessionLevel的Cache吧?),接下来通过下面的参数:


 EntityEntry e = new EntityEntry(
    status,
    loadedState,
    rowId,
    id,
    version,
    lockMode,
    existsInDatabase,
    persister,
    session.getEntityMode(),
    disableVersionIncrement,
    lazyPropertiesAreUnfetched
 );


组建一个EntityEntry对象,再利用如下语句entityEntries.put(entity, e)把这个新建的EntityEntry作为value同时那个DB数据的包装产物entity作为Key也放入到PersistenceContext里类型为Map的entityEntries对象中.这样就完成了数据从DB到PersistenceContext里迁移,而且在PersistenceContext里已有了Hibernate意义上的LockMode.

 

 2,这样当开一个Session并利用此Session来get某一个Java对象时,就会先从PersistenceContext里Map来取,若PersistenceContext里有,就取出.这时就要比较当前Session里取Java对象时的LockMode与PersistenceContext里对应EntityEntry里已有的LockMode,若前者大于后者就要来一次upgradeLock,毕竟当把这个Java对象从PersistenceContext里传给业务层后就要保证这个Java对象拥有一个高级别的排它锁,以防止别的Session偷偷地给改掉.这就是方法upgradeLock产生的背景,也正因为此upgradeLock方法也只出现在loadFromSessionCache里. -->不错,把upgradeLock这个方法放在PersistenceContext里来理解一下就通了.

有了上面的分析,对upgradeLock方法的理解就完成一半了.再往下走,就是看这个目标怎么实现了.

就我现在的理解来看,在实现上这个upgradeLock有三个层面的操作:


 1,二级缓存层面:通过生成一个包含当前Session及相关重要属性的CacheKey来锁定,也就是注明在二级缓存中想的那个Java对象已有CacheKey占有了,其它的"哥们儿"就别再花心思想这事了.


 2,PersistenceContext层面:有判断是否isVersioned,从而来保证Version的一致;在PersistenceContext层面来更新LockMode的级别.


 3,DB层面的事务隔离级别:
  persister.lock( entry.getId(), entry.getVersion(), object, requestedLockMode, source );
  下面又有:
   PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
  于是我就连蒙带猜地认为在DB层面上触及到事务的隔离级别了.

 

到结尾处有一个问题:
 if ( persister.hasCache() ) {
     persister.getCache().release(ck, lock );
 }

 

怎么finally里的代码块把前面刚刚Lock的给CacheKey的Entity给放了呢?这又不是session里的Trasaction已经结束了.想不明白,这个以后再慢慢体会吧.

 

不过看了对finally做的如下注释,
 "the database now holds a lock + the object is flushed from the cache,so release the soft lock"
虽说没有明白这个finally的作用,但似乎有些验证了前面关于"DB层面的事务隔离级别"的猜想.


这个方法终于搞完了.

作为补充,说一下,Hibernate在commit Trasaction时会把EntityEntry里的LockMode重置成最低级别的LockMode.NONE.

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页