關系數(shù)據庫映射(工作單元模式)-Hibernate實現(xiàn)

                                  注:主要是簡單分析一下Hibernate對于工作單元模式的實現(xiàn)


1. 首先,我們看一下在Hibernate中保存一個Entity對象典型的代碼如下:


private Long createAndStorePerson(String firstname, String lastname) {

        Session session 
= HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Person thePerson 
= new Person();
        thePerson.setFirstname(firstname);
        thePerson.setLastname(lastname);

        session.save(thePerson);

        session.getTransaction().commit();

        
return thePerson.getId();
}


2. 由上可以看出Hibernate中對應的工作單元就是Session,其中Session的類圖如下圖所示

 

我們參考一下上篇文章中提到得工作單元模式實現(xiàn)的幾種方式,按我個人理解,Hibernate的實現(xiàn)方式應該最接近于[由調用者注冊]的方式,而調用者注冊通知工作單元的操作被包裝起來,包裝在save/get等方法中,在這些方法中既更新對象又通知工作單元


3.我們以save方法為例:

public Serializable save(Object obj) throws HibernateException {
            SaveOrUpdateEvent event 
= new SaveOrUpdateEvent(entityName, object, this);
            SaveOrUpdateEventListener[] saveEventListener 
= listeners.getSaveEventListeners();
            
for ( int i = 0; i < saveEventListener.length; i++ ) {
                saveEventListener[i].onSaveOrUpdate(event);
            }
            
return event.getResultId();
        }

從上面的代碼可以看出,實際上save的實際操作不過是激活了一個SaveOrUpdateEventListener監(jiān)聽器,實際的工作由監(jiān)聽器完成工作.而監(jiān)聽器會完成怎樣的工作呢?總的來說保存為將來實際執(zhí)行數(shù)據庫做準備的各種信息。其中關注幾個關鍵性的接口:EventSource、SessionImplementor、PersistenceContext.等,依據幾個關鍵字應該大概能推測其功能其中SessionImplementor就是定義了Session和Hibernate其它部分之間的聯(lián)系,比如Hibernate和EntityPersister或者Type之間的聯(lián)系.


4. 為了了解Listener監(jiān)聽器到底執(zhí)行了何種操作,我們看由結果來進行推導.因為真正執(zhí)行數(shù)據庫的操作是在Transaction事務commit時,執(zhí)行了Flush操作.我們現(xiàn)在就看實際的Flush操作干了些什么?

public void onFlush(FlushEvent event) throws HibernateException {
        
final EventSource source = event.getSession();
        
if ( source.getPersistenceContext().hasNonReadOnlyEntities() ) {
            
            flushEverythingToExecutions(event);
            performExecutions(source);
            postFlush(source);
        
            
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
                source.getFactory().getStatisticsImplementor().flush();
            }
            
        }
    }


5. 其中主要是執(zhí)行了
flushEverythingToExecutions(event); performExecutions(source); postFlush(source);三個方法

flushEverythingToExecutions的doc(主要是做好各種準備工作)

Coordinates the processing necessary to get things ready for executions as db calls by preping the session
caches and moving the appropriate entities and collections to their respective
execution queues.
 
performExecutions的doc(按一定順序執(zhí)行所有SQL和二級緩存更新)

Execute all SQL and second-level cache updates, in a special order

postFlush的doc(執(zhí)行下面幾個步驟,主要是做一些收尾工作)

1. Recreate the collection key -> collection map
2. rebuild the collection entries
3. call Interceptor.postFlush()


而其中真正所執(zhí)行的那個操作就是ActionQueue中的

public void executeActions() throws HibernateException {
        executeActions( insertions );
        executeActions( updates );
        executeActions( collectionRemovals );
        executeActions( collectionUpdates );
        executeActions( collectionCreations );
        executeActions( deletions );
}


6. 這只是對Hibernate工作單元的一個簡單描述,具體工作單元需要實現(xiàn)的細節(jié),也就是Listener和最后Flush結合起來實際執(zhí)行的操作,包含幾個獨立的議題,需要單獨拿出來討論。



參考資料:
http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/index.html