`

Spring与Hibernate结合的细节源码分析(一)

    博客分类:
  • SSH
阅读更多
    本文基于SPRING2.56,HIBERANTE3.25及Oracle10g classes14.jar驱动,介绍SPRING与HIBERNATE是如何配合的细节,如SESSION、 事务、数据库连接何时打开与关闭;如果调用不是发自请求,不经过FILTER(如定时器对SERVICE调用),如何做到从头到尾只用一个SESSION? 此时SESSION需不需要手动关闭?从SESSION取得的数据库连接需不需要关闭,  看完本文,你会清楚里面每一个细节。
两种访问系统的路径:
1、request-->filters(spring and struts)-->actions-->AOP(transaction)-->services-->dao-->db
2、timer(run)->AOP(transaction)-->services-->dao-->db
    下面是调用链的图示



在WEB.XML配置了OpenSessionInViewFilter,整个请求只用一个SESSION,
在ACTION与SERVICE之间使用SPRING的AOP配置事务拦截器,所以事务范围涵盖整个SERVICE的方法调用,
DAO中一般使用SPRING的HibernateTemplate对象操作数据库
首先看OpenSessionInViewFilter在web.xml和事务拦截器相关配置
       <!--web.xml-->
 <filter>
		<filter-name>openSessionInViewFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
		</filter-class>
		<init-param>
			<param-name>singleSession</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	/////SRPING配置文件中事务拦截器相关配置
	<!-- hibernate 事务管理者 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	<!-- hibernate 事务拦截器 -->
	<bean id="transactionInterceptor"
		class="org.springframework.transaction.interceptor.TransactionInterceptor">
		<!--   注入事务管理者 -->
		<property name="transactionManager" ref="transactionManager" />
		<property name="transactionAttributes">
			<!--   定义事务属性-->
			<props>
				<prop key="*">PROPAGATION_REQUIRED</prop>
				<prop key="insert*">PROPAGATION_REQUIRED</prop>
				<prop key="add*">PROPAGATION_REQUIRED</prop>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="update*">PROPAGATION_REQUIRED</prop>
				<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="noTran*">PROPAGATION_NOT_SUPPORTED,readOnly</prop>
			</props>
		</property>
	</bean>
	/////配置service自动代理
	<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<property name="beanNames">
			<!--   代理所有Service   -->
			<list>
				<value>*Service</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>transactionInterceptor</value>
			</list>
		</property>
	</bean>


//下面从FILTER开始分析代码
	//这是OpenSessionInViewFilter类的方法,请求到来时,此方法由父类OncePerRequestFilter的doFilter()方法调用,
	protected void doFilterInternal(
			HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		//取得SessionFactory实例,实际上就是调用WebApplicationContext.getBean("beanName"),
		SessionFactory sessionFactory = lookupSessionFactory(request);
		//在lookupSessionFactory方法里看到原来此FILTER还支持配置sessionFactory为的名字,默认就叫sessionFactory,如果想改成其它名字具体配置方式:
		//在web.xml中,<init-param><param-name>sessionFactoryBeanName</param-name><param-value>sessionFactory</param-value></init-param>
		
		//此次调用有无打开SESSION,有的话在finally块关闭
		boolean participate = false;
		//是否单SESSION模式(上文web.xml中配置了),注意这并不意味着每个请求只用一个connection,下文详解
		if (isSingleSession()) {//这里我只分析单SESSION的情况,因为另一种情况不是此filter推荐的用法,就懒得看了
			// 单SESSION模式
			
			// 是否已经打开了SESSION,一般来说每个请求一开始是没有打开的
			if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
				participate = true;
			}
			else {
				logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
				//打开session,注意想在整个请求内部都用SESSION,这一句还不够,还必须有下面一句。getSession方法如何打开SESSION接下来讲解
				Session session = getSession(sessionFactory);
				//把SESSION放入SessionHolder,再用sessionFactory作为KEY,SessionHolder作为VALUE放入MAP,再把此MAP放入ThreadLocal
				//------不熟ThreadLocal看这,其他人跳过,ThreadLocal有两个主要的方法,get()和set(value),用法和MAP差不多,只是不需要提供KEY,
				//KEY就是当前线程,这样对于每个线程,只能往ThreadLocal里放入一个对象,在此放入了一个MAP。
				//不同的线程可以同时操作这个ThreadLocal对象,放入内容,因为各自有着不同的KEY------//
				TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
			}
		}
		else {//非单Session模式,本文不讨论此情况
			// deferred close mode
			if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
				// Do not modify deferred close: just set the participate flag.
				participate = true;
			}else {
				SessionFactoryUtils.initDeferredClose(sessionFactory);
			}
		}

		try {//SESSION已打开,往下调用,-->action-->aop-->service-->dao-->db
			filterChain.doFilter(request, response);
		}

		finally {//目标调用完成,关闭SESSION
			if (!participate) {//如果上文打开了SESSION
				if (isSingleSession()) {
					//从ThreadLocal里面把上面放入的MAP移除
					SessionHolder sessionHolder =
							(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
					logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
					//关闭SESSION
					closeSession(sessionHolder.getSession(), sessionFactory);
				}
				else {
					// deferred close mode
					SessionFactoryUtils.processDeferredClose(sessionFactory);
				}
			}
		}
	}
getSession方法
	//OpenSessionInViewFilter类,还是上面那个FILTER类
	protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
		//取SESSION,下文讲解
		Session session = SessionFactoryUtils.getSession(sessionFactory, true);
		//设置提交方式,getFlushMode默认返回FlushMode.NEVER,
		//NEVER看名字好像是永不提交,其实是外部显式调用FLUSH时才提交的意思,也许是因为名字不好,此变量已过时了,新的名字是FlushMode.MANUAL
		//如果请求是写操作,会在打开事务时被改成AUTO,
		FlushMode flushMode = getFlushMode();
		if (flushMode != null) {
			session.setFlushMode(flushMode);
		}
		return session;
	}
	
SessionFactoryUtils.doGetSession方法
	//SessionFactoryUtils类,取SESSION,此工具方法在以下两种情况被调用:在FILTER层开SESSION和在DAO层取SESSION去查数据库
	//在FILTER层调用时,没有事务(执行此方法的后半部份),在DAO层调用时,由于经过了AOP,开启了事务(执行方法的前半部份)
	//在没有JTA事务的环境中,此方法只是打开或取得一个SESSION,关于事务的事什么也没有做。
	private static Session doGetSession(
			SessionFactory sessionFactory, Interceptor entityInterceptor,
			SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
			throws HibernateException, IllegalStateException {

		Assert.notNull(sessionFactory, "No SessionFactory specified");
		//上文放入的sessionHolder在这里被取出来,如果调用来源于FILTER,则还没有放入,取出空,如果DAO层的调用,那么就不为空了
		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
		///--------------前半部份-------------------//////////////
		if (sessionHolder != null && !sessionHolder.isEmpty()) {// DAO中的调用,取得非空值,
			Session session = null;
			
			//如果:事务是否已开始 && sessionHolder中没有SESSION或只有一个默认SESSION
			if (TransactionSynchronizationManager.isSynchronizationActive() &&
					sessionHolder.doesNotHoldNonDefaultSession()) {
				//取出SESSION,里面主要判断一下SESSION有没有被关闭
				session = sessionHolder.getValidatedSession();
				//session不为空 && 事务没有开始,
				if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
					//在AOP中开始事务时,会将这个标志设为真,所以这里不会被执行,至少我还没有发现哪一次执行经过这里了
					logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
					TransactionSynchronizationManager.registerSynchronization(//注册一个SESSION
							new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
					sessionHolder.setSynchronizedWithTransaction(true);
					// 取出当前SESSION的提交方式
					FlushMode flushMode = session.getFlushMode();
					if (flushMode.lessThan(FlushMode.COMMIT) &&
							!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
						//如果是小于COMMIT,就是NEVER,那么改成自动
						session.setFlushMode(FlushMode.AUTO);
						//设置之前的提交模式
						sessionHolder.setPreviousFlushMode(flushMode);
					}
				}
			}
			else {//这里也是一般都不会被执行,因为AOP中已经开启了事务
				// No Spring transaction management active -> try JTA transaction synchronization.
				session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
			}
			if (session != null) {
				return session;
			}
		}
		////////-------------------后半部份--------------------------
		
		//来自FILTER的调用,一般sessionHolder为空
		logger.debug("Opening Hibernate Session");
		//调用HIBERNATE打开SESSION
		Session session = (entityInterceptor != null ?
				sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());

		// 当前请求是否已开启事务,FILTER中的调用,还没有到AOP层,事务没有打开,一般会执行ELSE
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
			logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
			SessionHolder holderToUse = sessionHolder;
			if (holderToUse == null) {
				holderToUse = new SessionHolder(session);
			}
			else {
				holderToUse.addSession(session);
			}
			if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
				session.setFlushMode(FlushMode.NEVER);
			}
			TransactionSynchronizationManager.registerSynchronization(
					new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
			holderToUse.setSynchronizedWithTransaction(true);
			if (holderToUse != sessionHolder) {
				TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
			}
		}
		else {
			// 上面没有找到事务,从sessionFactory中找,如果sessionFactory有配置JTA事务,则注册事务
			// 本文也没有配置JTA事务,所以里面什么也没有干,还是没有注册事务
			registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
		}

		// 如果不自动创建 && sessionHolder中没有session,则关闭SESSION
		if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
			closeSession(session);
			throw new IllegalStateException("No Hibernate Session bound to thread, " +
			    "and configuration does not allow creation of non-transactional one here");
		}
		//到此就在FILTER中取得了(或者说打开了)SESSION,下面就从ACTION调用SERVICE这一节了。
		return session;
	}
	

//下面开始到了ACTION的操作,action调用service,此service实际上是Spring动态生成的代理类,此代理类调用
//目标SERVICE类对应的方法前,要经过AOP拦截,下面我们对ACTION到SERVICE这中间经过的所有类方法代码分析一遍。
//我的应用在AOP层配置了一个事务拦截器,所以这中间的代码主要操作事务相关。
//动态生成的代理类代码看不到,从动态代理类下面的那个类(JdkDynamicAopProxy)开始吧
	
	//JdkDynamicAopProxy类,此方法被动态代理类调用
	//参数说明:proxy动态代理类对象,method目标方法,args目标方法参数
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation = null;
		Object oldProxy = null;
		boolean setProxyContext = false;

		//targetSource对象包含目标SERVICE对象
		TargetSource targetSource = this.advised.targetSource;
		Class targetClass = null;
		Object target = null;

		try {
			//如果目标类没有重载equals方法 && 目前正在调用目标类的equals方法,那直接调本类重载方法,
			//这样就不需要再往下走,不需要再开启事务等等多余的操作以至于浪费性能了,下面的几个IF都是做类似的事
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE);
			}
			if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return new Integer(hashCode());
			}
			if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal = null;

			//ProxyConfig类的exposeProxy属性,表示是否要将当前的代理对象放入AopContext中,
			//这样在你的Service中可以用AopContext.currentProxy()取得当前代理,相当于this引用,
			//不同于this引用的是,调用当前代理会被AOP拦截,而this不会。
			//此属性默认为FALSE,如果要打开,
			//在BeanNameAutoProxyCreator等代理类BEAN的配置中加入<property name="exposeProxy" value="true" />
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 取得目标(真实SERVICE对象)
			target = targetSource.getTarget();
			if (target != null) {
				targetClass = target.getClass();
			}

			// 取得所有拦截器
			List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果没有拦截器
			if (chain.isEmpty()) {
				// 直接调用目标
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
			}
			else {//有拦截器
				// 创建一个调用器对象
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 通过调用器往下调用目标或第一个拦截器
				retVal = invocation.proceed();
			}

			// 调用的返回结果目标类对象本身,就把它替换成代理类对象
			if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				retVal = proxy;
			}
			return retVal;
		}
		finally {//释放资源
			//主要是从当前线程清除代理类对象
			if (target != null && !targetSource.isStatic()) {
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
	
	
递归调用拦截器
	//ReflectiveMethodInvocation类,上面执行retVal = invocation.proceed();就进入到了这个方法
	//这个方法主要是递归调用各个拦截器,最后调用目标类
	public Object proceed() throws Throwable {
		//	判断是否还有拦截器要调用,
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			//没有拦截器了,调用目标
			return invokeJoinpoint();
		}

		//取出拦截器
		Object interceptorOrInterceptionAdvice =
		    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		
		//判断拦截器型,对不同类型的调用方法不一样,SPRING事务拦截器TransactionInterceptor是MethodInterceptor实现类,
		//不属于InterceptorAndDynamicMethodMatcher,执行ELSE
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			InterceptorAndDynamicMethodMatcher dm =
			    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {//方法匹配失败,跳过,继续递归
				return proceed();
			}
		}
		else {
			// 调用事务拦截器等,MethodInterceptor--林信良的SPRING手册介绍过个这接口如何使用
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
	
	
	
事务拦截器
	//TransactionInterceptor--SPRING的事务拦截器实现类,这个方法可以根据事务管理器的种类分类if和else上下两部分,
	//如果配置的是org.springframework.orm.hibernate3.HibernateTransactionManager等非CallbackPreferringPlatformTransactionManager接口实现类
	//则看只需要看if部份
	//了解这里工作原理很重要:
	//1、如果是请求发起的调用,流程路线为--FILTER打开Session,并且绑定到了线程信息中(TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session))),
	//在此方法里标志为旧SESSION,开始事务,调用目标,提交或回滚事务,判断如果是旧SESSION,则事务结束释放连接但不关闭SESSION,如果还用此SESSION再开启事务,再绑定另外的连接(所以上文说单SESSION并不等于同一个连接),最后在FILTER关闭SESSION。
	//2、如果不是请求发起的调用,如计划任务Timer.schedule(...)发起的SERVICE调用,流程为--在此方法打开SESSION,标志为新连接,开启事务,调用目标,提交或回滚事务,释放数据库连接,判断如果是新SESSION,则关闭SESSION。
	//总结如下:
	//1、只要有配置了此事务拦截器,底层使用SPRING的HibernateTemplate.getSession()、getSession().connection()取得连接或Spring提供的各种查询,那么SESSION和数据库连接的关闭不需要你操心,但是stateMent和ResultSet要记得关闭。
	//2、如果要在Timer的run方法中多次调用SERVICE时,也要实现OpenSessionInViewFilter这样的效果,那么使用如这句,结束时要记得自已关闭SESSION。
	//打开SESSION后:TransactionSynchronizationManager.bindResource(getSessionFactory(), new SessionHolder(session));
	//最后关闭SESSION:
	//SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
	//SessionFactoryUtils.closeSession(sessionHolder.getSession());
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		// 取得目标类名
		Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);

		// 通过类名及方法名,取得事务属性,即<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>这些内容
		final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
		//取得类名+方法名全称
		final String joinpointIdentification = methodIdentification(invocation.getMethod());
		//没有事务属性 || 事务管理者不是CallbackPreferringPlatformTransactionManager类型(事务采用回调方法实现的方式)
		if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
			//开始事务并创建事务信息对象(此对象主要包括事务属性和事务状态等信息),就是在这里调用了session.beginTransaction()方法
			//将事务信息以当前线程为KEY放入了TransactionAspectSupport.transactionInfoHolder对象中
			//注意:到这里如果当前取得到SessionHolder,那么SESSION就被标记成老SESSION,提交事务时就不会关闭之,反之那么session会在打开,并被标为新SESSION,提交事务时会把此SESSION关闭
			TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// 调用下一下拦截器,如果没有下一个拦截器,那么目标类会被调用
				retVal = invocation.proceed();
			}
			catch (Throwable ex) {
				// 发生异常时,在这里回滚,回滚时,除了rollBack,还执行session.clear(),setFlushMode(NEVER)等动作
				// 新SESSION会在此被关闭,老的则不会
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				//清理当前线程对应的事务信息,
				cleanupTransactionInfo(txInfo);
			}
			//未发生异常,提交事务,如果是新SESSION,会在此被关闭,老的则不会
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
			// 回调式的事务管理器,SPRING中只提供了一个WebSphereUowTransactionManager的具体实现,
			/**CallbackPreferringPlatformTransactionManager接口的注释
			 * Extension of the {@link org.springframework.transaction.PlatformTransactionManager}
			 * interface, exposing a method for executing a given callback within a transaction.
			 * <p>Implementors of this interface automatically express a preference for
			 * callbacks over programmatic <code>getTransaction</code>, <code>commit</code>
			 * and <code>rollback</code> calls. Calling code may check whether a given
			 * transaction manager implements this interface to choose to prepare a
			 * callback instead of explicit transaction demarcation control.*/
			// 大意应该是可以由此接口的具体实现来决定事务的控制,我的E文一般般,有错的就砸砖
			try {
				Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
						new TransactionCallback() {
							public Object doInTransaction(TransactionStatus status) {
								TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
								try {
									//往下调用
									return invocation.proceed();
								}
								catch (Throwable ex) {
									if (txAttr.rollbackOn(ex)) {
										// A RuntimeException: will lead to a rollback.
										if (ex instanceof RuntimeException) {
											throw (RuntimeException) ex;
										}
										else {
											throw new ThrowableHolderException(ex);
										}
									}
									else {
										// A normal return value: will lead to a commit.
										return new ThrowableHolder(ex);
									}
								}
								finally {
									cleanupTransactionInfo(txInfo);
								}
							}
						});

				// Check result: It might indicate a Throwable to rethrow.
				if (result instanceof ThrowableHolder) {
					throw ((ThrowableHolder) result).getThrowable();
				}
				else {
					return result;
				}
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
		}
	}

//这篇文章在打开和提交事务、同一SESSION多次切换不同事务的细节没有提及,下一篇讲解。
//本人水平很有限,错漏之处难免,请各位指出,并请手下留情...呵呵
  • 大小: 81.6 KB
分享到:
评论
19 楼 lgdlgd 2010-05-03  
lixia0417 写道
楼主:这句话“
如果:事务是否已开始 && sessionHolder中没有SESSION或只有一个默认SESSION”有点模糊啊,我觉得是用AOP声明式事务代理时,在开启事务的时候,已经有了一个新建了一个SessionHolder了,所以   if (TransactionSynchronizationManager.isSynchronizationActive() &&  
                sessionHolder.doesNotHoldNonDefaultSession()) 这个条件肯定是满足的。


在使用JTA的环境中,sessionHolder中的Session不使默认KEY存放,doesNotHoldNonDefaultSession()方法返回值就是false了,条件就不满足了。
18 楼 lixia0417 2010-05-02  
楼主:这句话“
如果:事务是否已开始 && sessionHolder中没有SESSION或只有一个默认SESSION”有点模糊啊,我觉得是用AOP声明式事务代理时,在开启事务的时候,已经有了一个新建了一个SessionHolder了,所以   if (TransactionSynchronizationManager.isSynchronizationActive() &&  
                sessionHolder.doesNotHoldNonDefaultSession()) 这个条件肯定是满足的。
17 楼 lixia0417 2010-05-01  
楼主的文章写得很详细,受教了,非常期待下一篇
16 楼 一剑飘红007 2010-03-18  
学习了,谢谢楼主。
15 楼 wangdgsc 2010-01-30  
这个确实不错,分析的比较的详细,谢谢
14 楼 Purking 2010-01-30  
非常棒, 太感谢楼主了, 解决了一直以来的困惑.
13 楼 mooninday 2010-01-28  
必须要mark下,工作做好了来学习
12 楼 jefyjiang 2010-01-27  
mark一下,以后学习!写得好!
11 楼 liangsongzhe 2010-01-27  
非常感谢^^
10 楼 lgdlgd 2010-01-27  
fu cktianya 写道
这么麻烦么?我记得不用这么多吧?

能讲讲使用openSessionInFilter的好处么?

我以前写的配置,都没有使用这个东西,所以不是很了解


配置的方法不是只有一种,我这只是其中一种,运行流程是一样的。

openSessionInFilter的好处:
1、在整个请求中只打开了一个SESSION,对象的创建少了。
2、避免页面出现延迟加载异常。
9 楼 heqishan 2010-01-27  
学习了。期待下一篇
8 楼 a_nuo 2010-01-27  
不是特别明白,回来在看
7 楼 wuwenyu 2010-01-27  
喜欢连载。。。。。
6 楼 shan7719515 2010-01-27  
标记一下,先谢了
5 楼 sunshy511 2010-01-27  
正在学习中,谢谢分享!
4 楼 fucktianya 2010-01-27  
这么麻烦么?我记得不用这么多吧?

能讲讲使用openSessionInFilter的好处么?

我以前写的配置,都没有使用这个东西,所以不是很了解
3 楼 li445970924 2010-01-27  
mark 等会来看
2 楼 Sunny_kaka 2010-01-27  
楼主辛苦了,能这样深入分析源码确实不容易.
1 楼 sing4j 2010-01-26  
学习,谢谢楼主。

相关推荐

    hibernate和Spring源码

    《深入剖析Hibernate与Spring源码》 在Java开发领域,Hibernate和Spring是两个不可或缺的开源框架,它们极大地简化了企业级应用的开发工作。本文将深入探讨这两个框架的内部机制,帮助开发者理解其核心原理,从而更...

    Spring4 Hibernate4 jersey项目源码

    本篇文章将深入探讨一个基于Spring4、Hibernate4和Jersey实现的rest风格系统的源码,揭示其设计思想和技术细节。 首先,Spring4作为Java企业级应用的主流框架,以其灵活的依赖注入(DI)和面向切面编程(AOP)为...

    spring源码分析(一)

    ### Spring源码分析知识点 #### 一、Spring框架概述 Spring框架是一个全面的企业级应用开发框架,它通过一系列模块化的组件来支持不同的应用场景和技术需求。Spring的核心价值在于提供了一种简洁的方式来解决企业...

    Spring+Hibernate小程序

    【Spring+Hibernate小程序】是一个基于Java的Web开发项目,它结合了Spring框架和Hibernate ORM工具,为构建数据库驱动的应用程序提供了高效且灵活的基础。这个项目的描述虽然为空,但我们可以从标题和标签中推断出...

    jsf2+primefaces+spring+hibernate案例

    【标题】"jsf2+primefaces+spring+hibernate案例"揭示了一个基于Java的全栈Web开发项目,它整合了几个关键的技术框架。JSF(JavaServer Faces)是Oracle公司推出的Java Web应用程序开发框架,用于构建用户界面。...

    初学struts+spring+hibernate

    7. **源码分析**:通过阅读和分析项目中的源码,可以更深入地理解这三个框架的实现细节和交互方式。 在实际开发中,这三者结合使用可以创建出强大且可维护的Java Web应用程序。深入学习并实践这些技术,对于提升...

    struts2+spring+hibernate实验设备管理系统+Asp.实验室管理系统

    Struts2、Spring和Hibernate是Java Web开发中的三大框架,它们各自在应用程序的不同层面发挥着重要作用。...开发者可以通过分析源码,掌握如何在实际项目中运用Struts2、Spring和Hibernate,提升自己的技能水平。

    网上商城系统 Hibernate Java JSP Struts Spring 源码+数据库+完整论文

    首先,Hibernate是一个对象关系映射(ORM)框架,它简化了Java应用与数据库之间的交互。通过Hibernate,开发者可以用面向对象的方式操作数据库,减少了SQL的直接编写,提高了开发效率和代码的可维护性。在本系统中,...

    基于Struts Spring Hibernate Ajax的电子宠物案例(源码+文档+数据库)

    总结来说,"基于Struts Spring Hibernate Ajax的电子宠物案例"是一个综合性的Java Web项目,它结合了多种技术来构建一个完整的应用。通过学习和研究这个案例,开发者可以深入了解这些技术的集成使用,提升在实际开发...

    jsp源码网上订餐系统(struts+spring+hibernate)130221

    ### jsp源码网上订餐系统(struts+spring+hibernate)130221 #### 知识点概述 本项目介绍了一个基于JSP(Java Server Pages)、Struts、Spring 和 Hibernate 构建的网上订餐系统。这些技术在 Java Web 开发领域非常...

    spring1.2.6源码

    Spring框架是Java开发中不可或缺的一部分,它以其IoC(Inversion...在实际的学习过程中,建议先从主要的接口和类开始,逐步深入到具体的实现细节,结合实际项目中的使用情况,将理论与实践相结合,以获得更深刻的领悟。

    oa项目应用Java Struts2 spring hibernate 源代码

    通过分析这些源代码,学习者可以深入理解如何在实际项目中整合Struts2、Spring和Hibernate,如何设计和实现业务逻辑,以及如何进行数据库操作。 学习这个OA项目源码,有助于提升以下几个方面的技能: 1. **MVC架构...

    Spring in Action 4加源码

    7. **源码分析**:附带的源码可以辅助读者理解书中示例的实现细节,加深对Spring框架的理解。读者可以通过分析源码学习到如何在实际项目中应用Spring的最佳实践。 8. **实战演练**:书中的案例都是基于真实世界的...

    SpringFramework3.2 源码 github源码gradle编译

    Spring Framework 3.2的源码分析可以从以下几个方面入手: 1. **IoC容器**:这是Spring的核心部分,负责管理对象的生命周期和依赖关系。通过XML配置或者注解的方式,开发者可以声明对象及其依赖,让IoC容器自动创建...

    Jbpm4.4 整合Spring Hibernate4

    "Jbpm4.4 整合Spring Hibernate4" 指的是一个集成项目,其中JBPM(Job Business Process Management)版本4.4被整合到Spring框架和Hibernate ORM工具的环境中。JBPM是一个开源的工作流管理系统,用于处理业务流程的...

    SpringMVC+Hibernate开发项目在线管理系统

    综合来看,"SpringMVC+Hibernate开发项目在线管理系统"是一个典型的Java Web开发实践,结合了Spring的MVC模式和Hibernate的ORM能力,构建出高效、可扩展的后台系统。源码文件可能包含了这些框架的配置、实体类、控制...

    Spring Framework v5.1.20-源码.zip

    总的来说,Spring Framework v5.1.20的源码分析是一个深入理解Java企业级开发、提升编程技能的宝贵机会。通过学习源码,我们可以更好地掌握Spring的精髓,从而在实际项目中发挥出更大的效能。无论是对于初学者还是...

    ssh 项目 struts hibernate spring

    SSH,全称是Struts2、Hibernate和Spring...对于初学者来说,分析SSH项目的源码是一个很好的学习途径,能深入理解Java Web开发的各个方面。而对于有经验的开发者,SSH项目的代码可以作为参考,提升项目开发效率和质量。

    spring-framework4.2x源码

    Spring Framework 4.2.x的源码分析,主要涉及以下几个核心模块: - **IoC(Inversion of Control)容器**:Spring的核心,负责管理对象的生命周期和依赖关系。通过XML、注解或Java配置实现,源码中可以研究...

Global site tag (gtag.js) - Google Analytics