关系数据库映射(工作单元模式)-Hibernate实现

                                  注:主要是简单分析一下Hibernate对于工作单元模式的实现


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的类图如下图所示

 

我们参考一下上篇文章中提到得工作单元模式实现的几种方式,按我个人理解,Hibernate的实现方式应该最接近于[由调用者注册]的方式,而调用者注册通知工作单元的操作被包装起来,包装在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监听器,实际的工作由监听器完成工作.而监听器会完成怎样的工作呢?总的来说保存为将来实际执行数据库做准备的各种信息。其中关注几个关键性的接口:EventSource、SessionImplementor、PersistenceContext.等,依据几个关键字应该大概能推测其功能其中SessionImplementor就是定义了Session和Hibernate其它部分之间的联系,比如Hibernate和EntityPersister或者Type之间的联系.


4. 为了了解Listener监听器到底执行了何种操作,我们看由结果来进行推导.因为真正执行数据库的操作是在Transaction事务commit时,执行了Flush操作.我们现在就看实际的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. 其中主要是执行了
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(按一定顺序执行所有SQL和二级缓存更新)

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

postFlush的doc(执行下面几个步骤,主要是做一些收尾工作)

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


而其中真正所执行的那个操作就是ActionQueue中的

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


6. 这只是对Hibernate工作单元的一个简单描述,具体工作单元需要实现的细节,也就是Listener和最后Flush结合起来实际执行的操作,包含几个独立的议题,需要单独拿出来讨论。



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