News是一,News_Pic是多,
sql = "from News as news";
在hibernate中,默认lazy=false,这样,在列表显示时,查询News时,对应的News_Pic的查询也会产生,
如果此时设置为lazy=true,即可解决此问题,
但是如果为ture,对显示News的具体信息(包括对应的News_Pic)时就会报错
failed to lazily initialize a collection of role:
no session or session was closed at
所以最终的解决办法是,lazy=false,无非是多显示几条sql
或者可以查询部分字段(需要的,不带pic的)
sql = "select news.id,news.title from News as news";
但在页面上就必须这样显示了<ww:property value="top[0]"></ww:property>
- <ww:property value="top[0]"/>
投影查询
不过这样以后,维护相对来说麻烦些,如果不是报表。最好不要这样做
另一种解决办法,就是使用OpenSessionInView.修改web.xml即可,加入以下代码即可
- <filter>
- <filter-name>OpenSessionInViewFilterfilter-name>
- <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilterfilter-class>
- <init-param>
- <param-name>singleSessionparam-name>
- <param-value>trueparam-value>
- init-param>
- filter>
- <filter-mapping>
- <filter-name>OpenSessionInViewFilterfilter-name>
- <url-pattern>*.actionurl-pattern>
- filter-mapping>
但是这样虽然解决了查询问题,但是在update,delete等操作上就又报错:
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.
网上又说
尽管Open Session In View看起来还不错,其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代码,这个方法实际上是被父类的doFilter调用的,因此,我们可以大约了解的OpenSessionInViewFilter调用流程: request(请求)->open session并开始transaction->controller->View(Jsp)->结束transaction并close session.
一切看起来很正确,尤其是在本地开发测试的时候没出现问题,但试想下如果流程中的某一步被阻塞的话,那在这期间connection就一直被占用而不释放。最有可能被阻塞的就是在写Jsp这步,一方面可能是页面内容大,response.write的时间长,另一方面可能是网速慢,服务器与用户间传输时间久。当大量这样的情况出现时,就有连接池连接不足,造成页面假死现象。
Open Session In View是个双刃剑,放在公网上内容多流量大的网站请慎用。