Hibernate源码分析

来源:互联网 发布:北京超图软件 股票 编辑:程序博客网 时间:2024/06/06 02:39
</pre><!--?xml version="1.0" encoding="UTF-8" standalone="no"?--><div style="font-family: Arial;font-size:14px;">Hibernate一般被我们作为数据库持久化工具使用,下面是我在使用过程中对工具使用过程中调试跟踪的一些记录。</div><div style="font-family: Arial;font-size:14px;"></div><div style="font-family: Arial;font-size:14px;">我们一般在applicationContext.xml里如上配置,打开类AnnotationSessionFactoryBean.java,看该类的构造函数及父类的构造函数</div><div style="font-family: Arial;font-size:14px;"><pre name="code" class="html"><bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">        <property name="configLocation"]]>            <value>classpath:hibernate.cfg.xml</value>        </property></bean>


public AnnotationSessionFactoryBean() {         setConfigurationClass(AnnotationConfiguration.class); }
<pre name="code" class="java">public AnnotationSessionFactoryBean() {                setConfigurationClass(AnnotationConfiguration.class);        }        @Override        public void setConfigurationClass(Class configurationClass) {                if (configurationClass == null || !AnnotationConfiguration.class.isAssignableFrom(configurationClass)) {                        throw new IllegalArgumentException(                                        "AnnotationSessionFactoryBean only supports AnnotationConfiguration or subclasses");                }                super.setConfigurationClass(configurationClass);        }



org.hibernate.cfg.Configuration  doConfig(File f)会使用hibernate.cfg.xml配置好之后调用buildSessionFactory()

org.springframework.beans.factory.InitializingBean  void afterPropertiesSet()方法可见,bean的配置参数设置之后,该函数会被调用 

org.springframework.orm.hibernate3.AbstractSessionFactoryBean 作为AnnotationSessionFactoryBean的父类实现了该接口,于是sessionFactory被构造出来。

public void afterPropertiesSet() throws Exception {                SessionFactory rawSf = buildSessionFactory();                this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);                afterSessionFactoryCreation();        }
我们在dao层一般使用getSession().load(id);getSession().save(obj);getSession().delete(obj)getSession().update(obj);等等方式实现CRUD,这些都会调用到org.session.impl.sessionImpl类下面的fireDelete(pram...),fireLoad(pram...),fireSaveOrUpdate(pram...)等方法,以delete为例子添加进去的deleteEventListener调用onDelete(DeleteEventevent)方法---》publicvoid onDelete(DeleteEvent event, Set transientEntities)

EntityEntry entityEntry = persistenceContext.getEntry( entity );                if ( entityEntry == null ) {}                else {                        log.trace( "deleting a persistent instance" );                        if ( entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE ) {                                log.trace( "object was already deleted" );                                return;                        }                        persister = entityEntry.getPersister();                        id = entityEntry.getId();                        version = entityEntry.getVersion();                }deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), persister, transientEntities );
可以看出,需要现在持久层查找该实体,找不到需要添加到持久层,找到了就可以准备删除。然后跳转deleteEntity方法,

session.getActionQueue().addAction(newEntityDeleteAction(entityEntry.getId(),deletedState,version,entity,persister,isCascadeDeleteEnabled,session));查看该Action的excite方法,

final CacheKey ck;if (persister.hasCache() ) {ck = new CacheKey( ...);lock = persister.getCacheAccessStrategy().lockItem( ckversion );
}并锁定缓存中的该数据,下方代码显示,需再缓存中删除,但我看不出来persistenceContext.removeEntity()和cacheAccessStrategy.remove的区别,知道的还请告知。

          if ( !isCascadeDeleteEnabled && !veto ) {                        persister.delete( id, version, instance, session );                }                                final PersistenceContext persistenceContext = session.getPersistenceContext();                EntityEntry entry = persistenceContext.removeEntry( instance );                if ( entry == null ) {                        throw new AssertionFailure( "possible nonthreadsafe access to session" );                }                entry.postDelete();                persistenceContext.removeEntity( entry.getEntityKey() );                persistenceContext.removeProxy( entry.getEntityKey() );                                if ( persister.hasCache() ) {                        persister.getCacheAccessStrategy().remove( ck );                }
而查询load不同,会涉及到sessionCache与secondLevelCache。

Object doLoad(final LoadEvent event,                        final EntityPersister persister,                        final EntityKey keyToLoad,                        final LoadEventListener.LoadType options) {Object entity = loadFromSessionCache( event, keyToLoad, options );                        return entity;                }                entity = loadFromSecondLevelCache(event, persister, options);                if ( entity != null ) {                     return entity             }             return loadFromDatasource(event, persister, keyToLoad, options);}
顺序是先一级缓存,然后二级缓存,然后数据库。在不同位置找到有不同处理,如果从数据库来,要将该实体添加至SessionCache里,如果从二级缓存来我看不出来做什么了。

暂时到这,

github: gitHub地址


0 0
原创粉丝点击