当前位置:首页 > 开发 > 编程语言 > Hibernate > 正文

Hibernate源码学习六

发表于: 2013-09-22   作者:bsr1983   来源:转载   浏览次数:
摘要: 接源码学习五的内容,sessionFactory创建好之后,就是打开数据库连接,执行数据库操作了。         主方法中的代码为: UserInfo user = new UserInfo(); user.setName("ibsrapp"); user.setPassword("ibsrapp

接源码学习五的内容,sessionFactory创建好之后,就是打开数据库连接,执行数据库操作了。

 

      主方法中的代码为:

UserInfo user = new UserInfo();
user.setName("ibsrapp");
user.setPassword("ibsrapp");
user.setBirthday(new Date());
//获取一个session
	Session session = sessionFactory.openSession();

 我们来看一下打开一个Session的具体过程,即openSession()方法做了些什么。

public Session openSession() throws HibernateException {
		return withOptions().openSession();
	}

 withOptions()的代码为:

public SessionBuilderImplementor withOptions() {
		return new SessionBuilderImpl( this );
	}

 即创建一个SessionBuilderImpl对象。SessionBuilderImpl是一个静态类,具体定义如下:

static class SessionBuilderImpl implements SessionBuilderImplementor
该类是
public final class SessionFactoryImpl
		implements SessionFactoryImplementor
的一个静态内部类。SessionFactoryImpl类的构造函数如下:
SessionBuilderImpl(SessionFactoryImpl sessionFactory) {
			this.sessionFactory = sessionFactory;
			this.sessionOwner = null;
			final Settings settings = sessionFactory.settings;

			// set up default builder values...
			//设置缺省值
			this.interceptor = sessionFactory.getInterceptor();
			//连接释放的模式
			this.connectionReleaseMode = settings.getConnectionReleaseMode();
			//会话是否自动关闭
			this.autoClose = settings.isAutoCloseSessionEnabled();
			this.flushBeforeCompletion = settings.isFlushBeforeCompletionEnabled();

			if ( sessionFactory.getCurrentTenantIdentifierResolver() != null ) {
				tenantIdentifier = sessionFactory.getCurrentTenantIdentifierResolver().resolveCurrentTenantIdentifier();
			}
		}

 可见只是将SessionFactoryImpl对象的很多属性拷贝过来了。

而具体的打开Session方法的代码如下:

public Session openSession() {
			return new SessionImpl(
					connection,
					sessionFactory,
					sessionOwner,
					getTransactionCoordinator(),
					autoJoinTransactions,
					sessionFactory.settings.getRegionFactory().nextTimestamp(),
					interceptor,
					flushBeforeCompletion,
					autoClose,
					connectionReleaseMode,
					tenantIdentifier
			);
		}

 即根据构造函数中初始化的变量,构造出一个org.hibernate.internal.SessionImpl对象。

public final class SessionImpl extends AbstractSessionImpl implements EventSource

 可以看到org.hibernate.internal.SessionImpl也是一个final类,其基继承了org.hibernate.internal.AbstractSessionImpl并实现了org.hibernate.event.spi.EventSource接口

org.hibernate.internal.AbstractSessionImpl的定义如下:

public abstract class AbstractSessionImpl implements Serializable, SharedSessionContract, SessionImplementor, TransactionContext

 查看其代码,可知该类中包含了一些关于创建、执行Query以及HQL执行计划、本地SQL执行计划以及JDBC访问、事务等相关的方法及私有内部类。

org.hibernate.event.spi.EventSource接口的定义如下:

public interface EventSource extends SessionImplementor, Session

 其继承了org.hibernate.event.spi.SessionImplementor, org.hibernate. Session这两个接口,查看这两个接口的定义,可以知道很多常用的查询方法,如loadgetlist等都是在这两个接口中定义的。而Session接口中还包含一个publicinterface LockRequest的内部接口。用于定义锁相关的接口。

  接下来看看openSession方法中调用的构造函数的具体代码:

SessionImpl(
			final Connection connection,
			final SessionFactoryImpl factory,
			final SessionOwner sessionOwner,
			final TransactionCoordinatorImpl transactionCoordinator,
			final boolean autoJoinTransactions,
			final long timestamp,
			final Interceptor interceptor,
			final boolean flushBeforeCompletionEnabled,
			final boolean autoCloseSessionEnabled,
			final ConnectionReleaseMode connectionReleaseMode,
			final String tenantIdentifier) {
		//调用父类构造方法
		super( factory, tenantIdentifier );
		//根据传递的参数设置本地变量的值
		this.timestamp = timestamp;
		this.sessionOwner = sessionOwner;
		//初始化拦截器
		this.interceptor = interceptor == null ? EmptyInterceptor.INSTANCE : interceptor;
		//初始化动作序列
		this.actionQueue = new ActionQueue( this );
		//初始化持久类上下文
		this.persistenceContext = new StatefulPersistenceContext( this );
		//设置是否自动关闭Session
		this.autoCloseSessionEnabled = autoCloseSessionEnabled;
		//设置执行完成前是否刷新缓存
		this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
		//如果事务调度为null,则初始化一个事务调度器
		if ( transactionCoordinator == null ) {
			this.isTransactionCoordinatorShared = false;
			this.connectionReleaseMode = connectionReleaseMode;
			this.autoJoinTransactions = autoJoinTransactions;

			this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
			this.transactionCoordinator.getJdbcCoordinator().getLogicalConnection().addObserver(
					new ConnectionObserverStatsBridge( factory )
			);
		}
		else {
			if ( connection != null ) {
				throw new SessionException( "Cannot simultaneously share transaction context and specify connection" );
			}
			this.transactionCoordinator = transactionCoordinator;
			this.isTransactionCoordinatorShared = true;
			this.autoJoinTransactions = false;
			if ( autoJoinTransactions ) {
				LOG.debug(
						"Session creation specified 'autoJoinTransactions', which is invalid in conjunction " +
								"with sharing JDBC connection between sessions; ignoring"
				);
			}
			if ( connectionReleaseMode != transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode() ) {
				LOG.debug(
						"Session creation specified 'connectionReleaseMode', which is invalid in conjunction " +
								"with sharing JDBC connection between sessions; ignoring"
				);
			}
			this.connectionReleaseMode = transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode();

			// add a transaction observer so that we can handle delegating managed actions back to THIS session
			// versus the session that created (and therefore "owns") the transaction coordinator
			transactionObserver = new TransactionObserver() {
				@Override
				public void afterBegin(TransactionImplementor transaction) {
				}

				@Override
				public void beforeCompletion(TransactionImplementor transaction) {
					if ( isOpen() && flushBeforeCompletionEnabled ) {
						SessionImpl.this.managedFlush();
					}
					beforeTransactionCompletion( transaction );
				}

				@Override
				public void afterCompletion(boolean successful, TransactionImplementor transaction) {
					afterTransactionCompletion( transaction, successful );
				//如果当前连接是打开的,并且自动关闭选项可用,则关闭连接
					if ( isOpen() && autoCloseSessionEnabled ) {
						//关闭连接
						managedClose();
					}
					transactionCoordinator.removeObserver( this );
				}
			};

			transactionCoordinator.addObserver( transactionObserver );
		}

		loadQueryInfluencers = new LoadQueryInfluencers( factory );

		if (factory.getStatistics().isStatisticsEnabled()) {
			factory.getStatisticsImplementor().openSession();
		}

      if (tracing)
		   LOG.tracef( "Opened session at timestamp: %s", timestamp );
	}

 关于上面自动关闭连接的函数managedClose()的具体代码如下:

public void managedClose() {
		LOG.trace( "Automatically closing session" );
		close();
	}

 具体调用的close()的代码如下:

public Connection close() throws HibernateException {
		LOG.trace( "Closing session" );
		//检测当前会话是否已关闭,即成员变量closed的值是否为true
		if ( isClosed() ) {
			throw new SessionException( "Session was already closed" );
		}

		//
		if ( factory.getStatistics().isStatisticsEnabled() ) {
			factory.getStatisticsImplementor().closeSession();
		}

		try {
			//标示当前用来进行Hibernate引擎与实际数据库事务处理之间的//协调者是否共享,如果不共享,将其关闭
			if ( !isTransactionCoordinatorShared ) {
				return transactionCoordinator.close();
			}
			else {
				if ( getActionQueue().hasAfterTransactionActions() ){
					LOG.warn( "On close, shared Session had after transaction actions that have not yet been processed" );
				}
				else {
					transactionCoordinator.removeObserver( transactionObserver );
				}
				return null;
			}
		}
		finally {
			//设置会话关闭标示为true closed = true;
			setClosed();
			//
			cleanup();
		}
	}

 cleanup()方法的代码如下:

private void cleanup() {
		persistenceContext.clear();
	}

 具体的clear()方法代码,即将原有的持久化上下文中的很多持久化缓存清空:

public void clear() {
		for ( Object o : proxiesByKey.values() ) {
			if ( o == null ) {
				//entry may be GCd
				continue;
			}
			((HibernateProxy) o).getHibernateLazyInitializer().unsetSession();
		}
		for ( Map.Entry<PersistentCollection, CollectionEntry> aCollectionEntryArray : IdentityMap.concurrentEntries( collectionEntries ) ) {
			aCollectionEntryArray.getKey().unsetSession( getSession() );
		}
		arrayHolders.clear();
		entitiesByKey.clear();
		entitiesByUniqueKey.clear();
		entityEntryContext.clear();
//		entityEntries.clear();
		parentsByChild.clear();
		entitySnapshotsByKey.clear();
		collectionsByKey.clear();
		collectionEntries.clear();
		if ( unownedCollections != null ) {
			unownedCollections.clear();
		}
		proxiesByKey.clear();
		nullifiableEntityKeys.clear();
		if ( batchFetchQueue != null ) {
			batchFetchQueue.clear();
		}
		// defaultReadOnly is unaffected by clear()
		hasNonReadOnlyEntities = false;
		if ( loadContexts != null ) {
			loadContexts.cleanup();
		}
		naturalIdXrefDelegate.clear();
	}

 接下来主方法中中开启了一个事务

Transaction trans = session.beginTransaction();

 Hibernate中对应的函数如下:

public Transaction beginTransaction() throws HibernateException {
		errorIfClosed();
		Transaction result = getTransaction();
		result.begin();
		return result;
	}

 获取事务对象的代码如下:

public Transaction getTransaction() throws HibernateException {
		errorIfClosed();
		return transactionCoordinator.getTransaction();
	}

 即返回当前事务协调器中的事务对象

public TransactionImplementor getTransaction() {
		if ( ! open ) {
			throw new ResourceClosedException( "This TransactionCoordinator has been closed" );
		}
		pulse();
		return currentHibernateTransaction;
	}

 //发送心跳?

public void pulse() {
		getSynchronizationCallbackCoordinator().pulse();
		if ( transactionFactory().compatibleWithJtaSynchronization() ) {
			// the configured transaction strategy says it supports callbacks via JTA synchronization, so attempt to
			// register JTA synchronization if possible
			attemptToRegisterJtaSync();
		}
	}

 //发送当前同步回调协调器的心跳

getSynchronizationCallbackCoordinator().pulse();的方法代码

public void pulse() {
		//如果当前设置中的线程要追踪JTA,则将当前线程的id赋值给//registrationThreadId
		if ( settings.isJtaTrackByThread() ) {
			registrationThreadId = Thread.currentThread().getId();
		}
	}

 尝试注册JTA同步attemptToRegisterJtaSync()方法的代码:

private void attemptToRegisterJtaSync() {
		if ( synchronizationRegistered ) {
			return;
		}

		// Has the local transaction (Hibernate facade) taken on the responsibility of driving the transaction inflow?
		if ( currentHibernateTransaction.isInitiator() ) {
			return;
		}

		if ( ! transactionContext.shouldAutoJoinTransaction() ) {
			if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.MARKED_FOR_JOINED ) {
				LOG.debug( "Skipping JTA sync registration due to auto join checking" );
				return;
			}
		}

		// IMPL NOTE : At this point the local callback is the "maybe" one.  The only time that needs to change is if
		// we are able to successfully register the transaction synchronization in which case the local callback would  become
		// non driving.  To that end, the following checks are simply opt outs where we are unable to register the
		// synchronization
		//获取当前事务环境中的JTA平台
		JtaPlatform jtaPlatform = getTransactionEnvironment().getJtaPlatform();
		if ( jtaPlatform == null ) {
			// if no jta platform was registered we wont be able to register a jta synchronization
			return;
		}

		// Can we resister a synchronization
		if ( !jtaPlatform.canRegisterSynchronization() ) {
			LOG.trace( "registered JTA platform says we cannot currently resister synchronization; skipping" );
			return;
		}

		// Should we resister a synchronization
		if ( ! transactionFactory().isJoinableJtaTransaction( this, currentHibernateTransaction ) ) {
			LOG.trace( "TransactionFactory reported no JTA transaction to join; skipping Synchronization registration" );
			return;
		}

		//在当前JTA平台中注册同步回调协调器
jtaPlatform.registerSynchronization( new RegisteredSynchronization( getSynchronizationCallbackCoordinator() ) );
		synchronizationRegistered = true;
		LOG.debug( "successfully registered Synchronization" );
	}

 开启事务后,main执行保存方法:

session.save(user);

 涉及到的保存方法如下:

public Serializable save(Object obj) throws HibernateException {
		return save( null, obj );
	}

 //以配置的实体名称及要保存的对象为参数的保存方法

public Serializable save(String entityName, Object object) throws HibernateException {
		return fireSave( new SaveOrUpdateEvent( entityName, object, this ) );
	}

 //以保存或更新事件为参数的保存方法

private Serializable fireSave(SaveOrUpdateEvent event) {
		errorIfClosed();
		checkTransactionSynchStatus();
		checkNoUnresolvedActionsBeforeOperation();
		for ( SaveOrUpdateEventListener listener : listeners( EventType.SAVE ) ) {
			listener.onSaveOrUpdate( event );
		}
		checkNoUnresolvedActionsAfterOperation();
		return event.getResultId();
	}

 //事件监听器的保存事件或更新事件的响应方法

public void onSaveOrUpdate(SaveOrUpdateEvent event) {
		final SessionImplementor source = event.getSession();
		final Object object = event.getObject();
		final Serializable requestedId = event.getRequestedId();

		if ( requestedId != null ) {
			//assign the requested id to the proxy, *before*
			//reassociating the proxy
			if ( object instanceof HibernateProxy ) {
				( ( HibernateProxy ) object ).getHibernateLazyInitializer().setIdentifier( requestedId );
			}
		}

		// For an uninitialized proxy, noop, don't even need to return an id, since it is never a save()
		if ( reassociateIfUninitializedProxy( object, source ) ) {
			LOG.trace( "Reassociated uninitialized proxy" );
		}
		else {
			//initialize properties of the event:
			final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );
			event.setEntity( entity );
			event.setEntry( source.getPersistenceContext().getEntry( entity ) );
			//return the id in the event object
			event.setResultId( performSaveOrUpdate( event ) );
		}

	}

 //保存或更新处理

protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) {
		EntityState entityState = getEntityState(
				event.getEntity(),
				event.getEntityName(),
				event.getEntry(),
				event.getSession()
		);
		//按照当前实体的不同状态调用不同的事件响应方法
		switch ( entityState ) {
			case DETACHED://脱管状态
				entityIsDetached( event );
				return null;
			case PERSISTENT://持久态
				return entityIsPersistent( event );
			default: //TRANSIENT or DELETED瞬时态或已删除
				return entityIsTransient( event );
		}
	}

 //脱管状态实体对象的保存方法

protected void entityIsDetached(SaveOrUpdateEvent event) {

		LOG.trace( "Updating detached instance" );
//获取当前要保存的对象是否在当前会话的持久化上下文中
		if ( event.getSession().getPersistenceContext().isEntryFor( event.getEntity() ) ) {
			//TODO: assertion only, could be optimized away
			throw new AssertionFailure( "entity was persistent" );
		}
		//获取要保存的实体
		Object entity = event.getEntity();
		//根据要保存的实体的映射实体名称和实体类,获取实体映射
		EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), entity );
		
		event.setRequestedId(
				getUpdateId(
						entity, persister, event.getRequestedId(), event.getSession()
				)
		);
		//调用performUpdate方法
		performUpdate( event, entity, persister );

	}

 //脱管状态保存方法调用的实际保存方法

protected void performUpdate(
			SaveOrUpdateEvent event,
			Object entity,
			EntityPersister persister) throws HibernateException {

        final boolean traceEnabled = LOG.isTraceEnabled();
		if ( traceEnabled && !persister.isMutable() ) {
			LOG.trace( "Immutable instance passed to performUpdate()" );
		}

		if ( traceEnabled ) {
			LOG.tracev( "Updating {0}",
					MessageHelper.infoString( persister, event.getRequestedId(), event.getSession().getFactory() ) );
		}

		final EventSource source = event.getSession();
	//获取实体的key
		final EntityKey key = source.generateEntityKey( event.getRequestedId(), persister );
//检查唯一约束
		source.getPersistenceContext().checkUniqueness(key, entity);

		if (invokeUpdateLifecycle(entity, persister, source)) {
            reassociate(event, event.getObject(), event.getRequestedId(), persister);
            return;
        }

		// this is a transient object with existing persistent state not loaded by the session

		new OnUpdateVisitor(source, event.getRequestedId(), entity).process(entity, persister);

		// TODO: put this stuff back in to read snapshot from
        // the second-level cache (needs some extra work)
        /*Object[] cachedState = null;

        if ( persister.hasCache() ) {
        	CacheEntry entry = (CacheEntry) persister.getCache()
        			.get( event.getRequestedId(), source.getTimestamp() );
            cachedState = entry==null ?
            		null :
            		entry.getState(); //TODO: half-assemble this stuff
        }*/
		//将托管的对象加入当前的持久化上下文,当前对象就从脱管状态变为持久态了
		source.getPersistenceContext().addEntity(
				entity,
				(persister.isMutable() ? Status.MANAGED : Status.READ_ONLY),
				null, // cachedState,
				key,
				persister.getVersion( entity ),
				LockMode.NONE,
				true,
				persister,
				false,
				true // assume true, since we don't really know, and it doesn't matter
				);

		persister.afterReassociate(entity, source);

		if ( traceEnabled ) {
			LOG.tracev( "Updating {0}", MessageHelper.infoString( persister, event.getRequestedId(), source.getFactory() ) );
		}

		cascadeOnUpdate( event, persister, entity );
	}

 //级联更新

private void cascadeOnUpdate(SaveOrUpdateEvent event, EntityPersister persister, Object entity) {
		EventSource source = event.getSession();
		//增加级联级别
		source.getPersistenceContext().incrementCascadeLevel();
		try {
			new Cascade( CascadingAction.SAVE_UPDATE, Cascade.AFTER_UPDATE, source )
					.cascade( persister, entity );
		}
		finally {
		//减少级联级别	source.getPersistenceContext().decrementCascadeLevel();
		}
	}

 //用于处理持久态更新事件

protected Serializable entityIsPersistent(SaveOrUpdateEvent event) throws HibernateException {
		final boolean traceEnabled = LOG.isTraceEnabled();
		if ( traceEnabled ) {
			LOG.trace( "Ignoring persistent instance" );
		}
		EntityEntry entityEntry = event.getEntry();
		if ( entityEntry == null ) {
			throw new AssertionFailure( "entity was transient or detached" );
		}
		else {
			//实体的状态为已删除
			if ( entityEntry.getStatus() == Status.DELETED ) {
				throw new AssertionFailure( "entity was deleted" );
			}

			final SessionFactoryImplementor factory = event.getSession().getFactory();

			Serializable requestedId = event.getRequestedId();

			Serializable savedId;
			if ( requestedId == null ) {
				savedId = entityEntry.getId();
			}
			else {

				final boolean isEqual = !entityEntry.getPersister().getIdentifierType()
						.isEqual( requestedId, entityEntry.getId(), factory );

				if ( isEqual ) {
					throw new PersistentObjectException(
							"object passed to save() was already persistent: " +
									MessageHelper.infoString( entityEntry.getPersister(), requestedId, factory )
					);
				}

				savedId = requestedId;

			}

			if ( traceEnabled ) {
				LOG.tracev( "Object already associated with session: {0}", MessageHelper.infoString( entityEntry.getPersister(), savedId, factory ) );
			}

			return savedId;

		}
	}

 //瞬时态的保存更新事件响应

protected Serializable entityIsTransient(SaveOrUpdateEvent event) {

		LOG.trace( "Saving transient instance" );

		final EventSource source = event.getSession();

		EntityEntry entityEntry = event.getEntry();
		if ( entityEntry != null ) {
			if ( entityEntry.getStatus() == Status.DELETED ) {
				source.forceFlush( entityEntry );
			}
			else {
				throw new AssertionFailure( "entity was persistent" );
			}
		}

		Serializable id = saveWithGeneratedOrRequestedId( event );

		source.getPersistenceContext().reassociateProxy( event.getObject(), id );

		return id;
	}

 主方法中执行trans.commit();

public void commit() throws HibernateException {
		//当前事务未激活
		if ( localStatus != LocalStatus.ACTIVE ) {
			throw new TransactionException( "Transaction not successfully started" );
		}

		LOG.debug( "committing" );
		//事务提交前的处理,有三种不同的实现:JDBC、JTA、Container //Managed Transaction (CMT),提交事务和提交事务后的处理也是一样,有//这三种不同的实现
		beforeTransactionCommit();

		try {
			//提交事务
			doCommit();
			//将事务状态改为已提交
			localStatus = LocalStatus.COMMITTED;
			afterTransactionCompletion( Status.STATUS_COMMITTED );
		}
		catch ( Exception e ) {
			//如果提交过程中出现异常,则修改状态为提交失败
			localStatus = LocalStatus.FAILED_COMMIT;
			afterTransactionCompletion( Status.STATUS_UNKNOWN );
			throw new TransactionException( "commit failed", e );
		}
		finally {
			invalidate();
			afterAfterCompletion();
		}
	}

 主方法中提交完毕就是关闭SessionsessionFactory

session.close();//该代码在分析上面managedClose()的代码的时候就列举过了

  sessionFactory.close();

  代码如下:

public void close() throws HibernateException {
		if ( isClosed ) {
			LOG.trace( "Already closed" );
			return;
		}
		LOG.closing();
		isClosed = true;

		settings.getMultiTableBulkIdStrategy().release( jdbcServices, buildLocalConnectionAccess() );
		//清理当前实体持久类
		Iterator iter = entityPersisters.values().iterator();
		while ( iter.hasNext() ) {
			EntityPersister p = (EntityPersister) iter.next();
			if ( p.hasCache() ) {
				p.getCacheAccessStrategy().getRegion().destroy();
			}
		}
		//清理
		iter = collectionPersisters.values().iterator();
		while ( iter.hasNext() ) {
			CollectionPersister p = (CollectionPersister) iter.next();
			if ( p.hasCache() ) {
				p.getCacheAccessStrategy().getRegion().destroy();
			}
		}
		//访问缓存关闭
		cacheAccess.close();
		//清理查询计划缓存
		queryPlanCache.cleanup();
		
		if ( settings.isAutoDropSchema() ) {
			schemaExport.drop( false, true );
		}
		//调用会话工厂服务的删除会话工厂方法
		SessionFactoryRegistry.INSTANCE.removeSessionFactory(
				uuid,
				name,
				settings.isSessionFactoryNameAlsoJndiName(),
				serviceRegistry.getService( JndiService.class )
		);
		//调用会话工厂的观察者的会话工厂关闭事件方法
		observer.sessionFactoryClosed( this );
		//销毁服务注册
		serviceRegistry.destroy();
	}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Hibernate源码学习六

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
今天我开始攻略jQuery的心脏,css选择器。不过Sizzle是如此复杂的东西,我发现不能跟着John Resig的
作者:zuoxiaolong8810(左潇龙),转载请注明出处。 最近工作很忙,但当初打算学习spring源码的事
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客
分析了BasicSerializer和JavaSerializer,剩下的序列化类就比较简单了,其实最本质的是基本类型的序
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
接学习三中的内容,首先看一下如何根据配置文件创建一个SessionFactory,通过跟踪相关代码来了解其
ActivityManager在操作系统中有重要的作用,本文利用操作系统源码,逐步理清ActivityManager的框架
Nginx的启动过程   主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号