Spring 编程入门十大问题解答
failed to lazily initialize a collection of role: XXXXXXXX no session or session was closed
http://hi.baidu.com/kekemao1/blog/item/1b3099c4023b14ca38db4925.html
问题解决出自以上帖子!
Spring 编程入门十大问题解答
1 、如何学习Spring ? 你可以通过下列途径学习spring : (1) spring 下载包中doc 目录下的MVC-step-by-step 和sample 目录下的例子都是比较好的spring 开发的例子。 (2) AppFuse 集成了目前最流行的几个开源轻量级框架或者工具 Ant,XDoclet,Spring,Hibernate(iBATIS),JUnit,Cactus,StrutsTestCase,Canoo's WebTest,Struts Menu,Display Tag Library,OSCache,JSTL,Struts 。 你可以通过AppFuse 源代码来学习spring 。 AppFuse 网站:http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse (3)Spring 开发指南( 夏昕) (http://www.xiaxin.net/Spring_Dev_Guide.rar ) 一本spring 的入门书籍, 里面介绍了反转控制和依赖注射的概念,以及spring 的bean 管理,spring 的MVC ,spring 和hibernte ,iBatis 的结合。 (4) spring 学习的中文论坛 SpringFramework 中文论坛(http://spring.jactiongroup.net) Java 视线论坛(http://forum.javaeye.com) 的spring 栏目 2 、利用Spring 框架编程,console 打印出log4j:WARN Please initialize the log4j system properly ? 说明你的log4j.properties 没有配置。请把log4j.properties 放到工程的classpath 中,eclipse 的classpath 为bin 目录,由于编译后src 目录下的文件会拷贝到bin 目录下,所以你可以把log4j.properties 放到src 目录下。 这里给出一个log4j.properties 的例子:
log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
3 、出现 java.lang.NoClassDefFoundError? 一般情况下是由于你没有把必要的jar 包放到lib 中。 比如你要采用spring 和hibernate (带事务支持的话),你除了spring.jar 外还需要hibernat.jar 、aopalliance.jar 、cglig.jar 、jakarta-commons 下的几个jar 包。 http://www.springframework.org/download.html 下载spring 开发包,提供两种zip 包 spring-framework-
1.1.3
-with-dependencies.zip 和spring-framework-1.1.3.zip ,我建议你下载spring-framework-1.1.3-with-dependencies.zip 。这个zip 解压缩后比后者多一个lib 目录,其中有hibernate 、j2ee 、dom4j 、aopalliance 、jakarta-commons 等常用包。 4 、java.io.FileNotFoundException: Could not open class path resource [....hbm.xml], 提示找不到xml 文件? 原因一般有两个: (1) 该xml 文件没有在classpath 中。 (2)applicationContext-hibernate.xml 中的xml 名字没有带包名。比如:
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean" > <property name="dataSource" ><ref bean="dataSource"/ ></property > <property name="mappingResources" > <list > <value >User.hbm.xml </value > 错,改为: <value >com/yz/spring/domain/User.hbm.xml </value > </list > </property > <property name="hibernateProperties" > <props > <prop key="hibernate.dialect" > net.sf.hibernate.dialect.MySQLDialect </prop > <prop key="hibernate.show_sql" >true </prop > </props > </property ></bean >
5 、org.springframework.beans.NotWritablePropertyException: Invalid property 'postDao' of bean class ? 出现异常的原因是在application-xxx.xml 中property name 的错误。 <property name="...." > 中name 的名字是与bean 的set 方法相关的,而且要注意大小写。 比如
public class PostManageImpl extends BaseManage implements PostManage { private PostDAO dao = null; public void setPostDAO(PostDAO postDAO){ this.dao = postDAO; } }
那么xml 的定义应该是:
<bean id="postManage" parent="txProxyTemplate" > <property name="target" > <bean class="com.yz.spring.service.implement.PostManageImpl" > <property name="postDAO" ><ref bean="postDAO"/ ></property > 对 <property name="dao" ><ref bean="postDAO"/ ></property > 错 </bean > </property > </bean >
6 、Spring 中如何实现事务管理? 首先,如果使用mysql ,确定mysql 为InnoDB 类型。 事务管理的控制应该放到商业逻辑层。你可以写个处理商业逻辑的JavaBean ,在该JavaBean 中调用DAO ,然后把该Bean 的方法纳入spring 的事务管理。 比如:xml 文件定义如下:
< bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" ><property name="transactionManager" ><ref bean="transactionManager"/ ></property > <property name="transactionAttributes" > <props > <prop key="save*" >PROPAGATION_REQUIRED </prop > <prop key="remove*" >PROPAGATION_REQUIRED </prop > <prop key="*" >PROPAGATION_REQUIRED </prop > </props > </property > </bean > <bean id="userManage" parent="txProxyTemplate" > <property name="target" > <bean class="com.yz.spring.service.implement.UserManageImpl" > <property name="userDAO" ><ref bean="userDAO"/ ></property > </bean > </property > </bean >
com.yz.spring.service.implement.UserManageImpl 就是我们的实现商业逻辑的JavaBean 。我们通过parent 元素声明其事务支持。 7 、如何管理Spring 框架下更多的JavaBean ? JavaBean 越多,spring 配置文件就越大,这样不易维护。为了使配置清晰,我们可以将JavaBean 分类管理,放在不同的配置文件中。 应用启动时将所有的xml 同时加载。 比如: DAO 层的JavaBean 放到applicationContext-hibernate.xml 中,商业逻辑层的JavaBean 放到applicationContext-service.xml 中。然后启动类中调用以下代码载入所有的ApplicationContext 。
String[] paths = {"com/yz/spring/dao/hibernate/applicationContext-hibernate.xml", "com/yz/spring/service/applicationContext-service.xml"}; ctx = new ClassPathXmlApplicationContext(paths);
8 、web 应用中如何加载ApplicationContext ? 可以通过定义web.xml ,由web 容器自动加载。
<servlet > <servlet-name >context </servlet-name > <servlet-class >org.springframework.web.context.ContextLoaderServlet </servlet-class > <load-on-startup >1 </load-on-startup > </servlet > <context-param > <param-name >contextConfigLocation </param-name > <param-value >/WEB-INF/applicationContext-hibernate.xml </param-value > <param-value >/WEB-INF/applicationContext-service.xml </param-value > </context-param >
9 、在spring 中如何配置的log4j? 在web.xml 中加入以下代码即可。
<context-param > <param-name >log4jConfigLocation </param-name > <param-value >/WEB-INF/log4j.properties </param-value > </context-param >
10 、Spring 框架入门的编程问题解决了,我该如何更深地领会Spring 框架呢? 这两本书你该去看看。这两本书是由Spring 的作者Rod Johnson 编写的。
Expert One on one J2EE Design and Development Expert One on one J2EE Development Without EJB
你也该看看martinfowler 的Inversion of Control Containers and the Dependency Injection pattern 。
http://www.martinfowler.com/articles/injection.html
再好好研读一下spring 的文档。
http://www.jactiongroup.net/reference/html/index.html (中文版,未全部翻译)
failed to lazily initialize a collection of role: XXXXXXXX no session or session was closed
以下有2 种方法,第1 种是结合SPRING ,第2 种是采用了拦截器
Spring+Hibernate 中, 集合映射如果使用lazy="true" , 当PO 传到View 层时, 出现未初始化session 已关闭的错误,只能在dao 先初始化
parent.getChilds().size();
Spring 提供Open Session In View 来解决这个问题, 有两种方式 1. Interceptor
<!--</span><span style="COLOR: rgb(0,128,0)"> =========== OpenSession In View pattern ==============</span><span style="COLOR: rgb(0,128,0)">--> <bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors" ref="openSessionInViewInterceptor"/> <property name="mappings"> <props> ...... </props> </property> </bean>
2. Filter
<web-app> <filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate.support.OpenSessionInViewFilter </filter-class> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> </web-app>
第2 种解决方法:
Hibernate.initialize() 强制加载关联对象