转自:http://blog.csdn.net/aspdao/article/details/5472955
步骤1:将所有的*.hbm.xml文件中的lazy="false"改成lazy="true"
步骤2:替换MyEclipse自动添加的jar包cglib-2.1.3.jar为cglib-2.2_beta1.jar,否则会出现如下异常
?
java.lang.NullPointerException org.hibernate.tuple.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:372)
...
?
?
步骤3:在项目的web.xml中添加(注意这个Filter要在struts的Filter的前面)
- < listener > ??
- ????< listener-class > ??
- ????????org.springframework.web.context.ContextLoaderListener??
- ????</ listener-class > ??
- </ listener > ??
- < context-param > ??
- ????< param-name > contextConfigLocation </ param-name > ??
- ????< param-value > /WEB-INF/applicationContext.xml </ param-value > ??
- </ context-param > ???
- lt;filter> ??
- ????< filter-name > hibernateFilter </ 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 > ??
- < filter-mapping > ??
- ????< filter-name > hibernateFilter </ filter-name > ??
- ????< url-pattern > /* </ url-pattern > ??
- </ filter-mapping > ??
?
步骤4:将struts配置文件中的一段去掉(之前没有发现这里,导致配置完成后一部分懒加载还是抛异常)
javax.servlet.ServletException:
org.hibernate.LazyInitializationException:
could not initialize proxy - the owning Session was closed
?
?
- <!--???
- ????< plug-in ??
- ????????className = "org.springframework.web.struts.ContextLoaderPlugIn" > ??
- ????????< set-property ? property = "contextConfigLocation" ??
- ????????????value = "/WEB-INF/applicationContext.xml" ? /> ??
- ????</ plug-in > ??
- ?--> ??
?
?
至此,所有的页面访问全部都正常了,sql语句由原来的上百条减少到几条,(仅仅是那些必须的sql语句了),响应时间也由原来的几秒十几秒减少到 了1秒以内,多数为0.5秒,有的减少到0.1秒以内。可见效果有多么明显!!但是现在所有的查询操作没问题了,但是update和save还是不行,还 是哪里的配置不对,抛出的异常为:
javax.servlet.ServletException: org.springframework.dao.InvalidDataAccessApiUsageException:
Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL):
Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
?
?
?
?
?
这个异常产生的主要原因是DAO采用了Spring容器的事务管理策略,如果操作方法的名称和事务策略中指定的被管理的名称不能够匹配 上,spring 就会采取默认的事务管理策略(PROPAGATION_REQUIRED,read only).如果是插入和修改操作,就不被允许的,所以包这个异常
?
解决的办法是利用Spring的AOP,过滤那些update、delete、save、create等非只读操作,并将其设置正确的事务管理策略,而不是默认的设置。
?
在Spring配置文件applicationContext.xml中加入下面代码:
?
- < bean ? id = "transactionManager" ? class = "org.springframework.orm.hibernate3.HibernateTransactionManager" > ????
- ??< property ? name = "sessionFactory" > ????
- ??????< ref ? bean = "sessionFactory" /> ????
- ??</ property > ????
- </ bean > ????
- <!--?配置事务通知?--> ????
- < tx:advice ? id = "txAdvice" ? transaction-manager = "transactionManager" > ????
- ??< tx:attributes > ????
- ????< tx:method ? name = "save*" ? propagation = "REQUIRED" ? read-only = "false" /> ??
- ????< tx:method ? name = "create*" ? propagation = "REQUIRED" ? read-only = "false" /> ??
- ????< tx:method ? name = "delete" ? propagation = "REQUIRED" ? read-only = "false" /> ????
- ????< tx:method ? name = "find*" ? propagation = "REQUIRED" ? read-only = "true" /> ??
- ????< tx:method ? name = "list*" ? propagation = "REQUIRED" ? read-only = "true" /> ??
- ????< tx:method ? name = "get*" ? propagation = "REQUIRED" ? read-only = "true" /> ????
- ????< tx:method ? name = "*" ? read-only = "true" /> ????
- ??</ tx:attributes > ????
- </ tx:advice > ????
- <!--添加事务--> ???????
- < aop:config > ????
- ??<!--切入点--> ????
- ??< aop:pointcut ? id = "txPointCut" ? expression = "execution(*?cn.gov.ggj.service.impl.*.*(..))" /> ????
- ??<!--通知器--> ????
- ??< aop:advisor ? advice-ref = "txAdvice" ? pointcut-ref = "txPointCut" /> ????
- </ aop:config > ????
?
Eclipse不能识别<tx:advice/>标签
在开发Spring的过程中,有时会出现Eclipse不能识别<tx:advice/>标签。
提示出现以下错误:
The prefix "tx" for element "tx:advice" is not bound
?
原因是<beans>中要加入“xmlns:aop”的命名申明,并在“xsi:schemaLocation”中指定aop配置的schema的地址
配置文件如下:
?
- <? xml ? version = "1.0" ? encoding = "UTF-8" ?> ??
- < beans ? xmlns = "http://www.springframework.org/schema/beans" ??
- ?????xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" ??
- ?????xmlns:aop = "http://www.springframework.org/schema/aop" ??
- ?????xmlns:tx = "http://www.springframework.org/schema/tx" ??
- ?????xsi:schemaLocation ="??
- ?????http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.5.xsd??
- ?????http://www.springframework.org/schema/tx?http://www.springframework.org/schema/tx/spring-tx-2.5.xsd??
- ?????http://www.springframework.org/schema/aop?http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> ??
?
至此不会再报错了,下面解释一下aop中的设置
?
Spring使用 <tx:advice>和 <aop:config> 用来配置事务,具体如何配置你可以参考Spring文档。
我解释一下(*?cn.gov.ggj.service.impl.*.*(..))中几个通配符的含义:
第一个 * ―― 通配 任意返回值类型
第二个 * ―― 通配 包cn.gov.ggj.service.impl下的任意class
第三个 * ―― 通配 包cn.gov.ggj.service.impl下的任意class的任意方法
第四个 .. ―― 通配 方法可以有0个或多个参数
综上:包cn.gov.ggj.service.impl下的任意class的具有任意返回值类型、任意数目参数和任意名称的方法
?
?
之所以用一个Filter来解决Hibernate懒加载的问题,见下面文章的解释:
?
?
Hibernate的强大之处之一是懒加载功能,可以有效的降低数据库访问次数和内存使用量。但用的不好就会出现org.hibernate.LazyInitializationException。
这个异常出现的原因很简单,主要时在加载懒数据时Session已经关闭造成的,如下图:
?
那么OK,我们来考虑怎么解决吧。
我们只要在渲染JSP之前不要关闭Session,而在JSP渲染之后再关闭就OK啊。我们知道,在JSP/Servlet中,可以配置过滤器来实现这种功能。
?