2009年4月21日星期二

Funny and Interesting websites

有很多实用的新鲜的小软件,也可以为开发者提供创新的思路,值得推荐!

2009年4月20日星期一

Hibernate与MS sql server配合异常

  • 应用环境
两表Ta、Tb关联;在Ta中设有set集合
HBM文件中设有lazy="true"或lazy="false"
  • 现象:
当lazy设为true时,报异常no session or session is closed.
当lazy设为false时,报异常ResultSet can not re-read row data for column 1。
  • 探究
对于lazy为true时,Hibernate采用延迟检索,即仅在缓存中保存关联的外键,而没有其他的字段或属性的内容,只在需要使用时才去检索,而这时Hibernate的session已经被关闭,从而导致异常;
对于lazy为false时,Hibernate采用立即检索,即会在查询主表时同时填充其关联表的属性内容;而这时有可能会引发“结果集某列不能重复读”的异常,其原因在于MS的驱动。详情请见http://support.microsoft.com/kb/824106。前人总结如下:
(1)如果采用jdbc-odbc驱动,那么就必须按照查询顺序来一次读取(不论有没有p_w_picpath或text类型)
(2)如果采用微软提供的ms sql server jdbc driver,如果查询语句中,不存在p_w_picpath或text类型字段,那么可以按照无序获取
(3)如果采用微软提供的ms sql server jdbc driver,如果查询语句中,存在p_w_picpath或text类型字段,那么就必须按照顺序读取,否则就会报告Driver]ResultSet can not re-read row data for column之类的错误
(4)如果想不查询语句中有没有p_w_picpath或text类型字段,都可以不按照顺序获取,或重复获取。
其意思就是要求在读取Resultset是尽量按照查询顺序读取【且只能读一次】,尤其是在字段中含有文本等类型时。
  • 解决途径:
当lazy设为true时,报异常no session or session is closed.
  1. Open session in view:
  2. 在web.xml中添加过滤器<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>false</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
同时去掉struts配置中的plug-in节中有关Spring的配置,使用web.xml中的listener配置Spring。

对于不能重复读的异常【网络搜集】:
  1. 自己调整sql代码或者是JAVA代码,确保顺序一致,从左到右严格读取,应该就没有问题;
  2. 修改数据库设计:将表中text\image等字段能修改的前提下更改掉,如text类型可以替换成varchar等;
  3. 在connection url后面加上SelectMethod=cursor【测试无效,可能由于采用数据源配置,无法传递后续参数?】
  4. 把所有的outer-join="auto"
    改为
    outer-join="false"【适用于Hibernate2.Hibernate3没有测试】
  5. 更换sql驱动,采用第三驱动,要使用jTDS驱动,配置要做一些变动: 数据库URL:jdbc:jtds:sqlserver://localhost:1433;DatabaseName=XXX
驱动类:net.sourceforge.jtds.jdbc.Driver 其在sourceforge上的介绍中写到:
Open source pure Java JDBC 2.1 driver for the Microsoft SQL Server series (6.5, 7.0 and 2000). jTDS is the fastest JDBC driver for MSSQL Server and is a complete implementation of the JDBC spec.
项目页:http://sourceforge.net/projects/jtds/http://jtds.sourceforge.net/

总体说来,建议采用jTDS驱动;考虑Open session in view。


2009年4月13日星期一

有关Struts中Tiles使用的问题

1.出现空引用
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:524)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:435)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:40)


root cause

java.lang.NullPointerException
org.apache.struts.taglib.tiles.InsertTag.processName(InsertTag.java:527)
org.apache.struts.taglib.tiles.InsertTag.createTagHandler(InsertTag.java:482)
org.apache.struts.taglib.tiles.InsertTag.doStartTag(InsertTag.java:438)
org.apache.jsp.index_jsp._jspx_meth_tiles_005finsert_005f0(index_jsp.java:119)
org.apache.jsp.index_jsp._jspService(index_jsp.java:86)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:40)

其问题主要由于使用不当造成的!!!

通常Struts配置文件为
<plug-in classname="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-INF/tiles-def.xml">
<set-property property="moduleAware" value="true">
</set-property>
</plug-in>
则相应的tiles-def.xml定义为


<tiles-definitions>

<definition name="main.Layout" path="/layout.jsp">
<put name="header" type="page" value="/header.jsp">
</put>

</definition>
</tiles-definitions></set-property>
重点来了,其中path给出的layout.jsp为模板文件,而不是你直接访问的页面,其内容如下:
<html>
<head>

<title>My JSP 'layout.jsp' starting page</title>

</head>
<body>
<tiles:insert attribute="header"/>
</body>
</html>
因此,需要在实际被用户访问的页面里使用
<tiles:insert definition="main.Layout" />
才不会出错;而不是直接访问模板文件。切记!!!

2. 另外请注意Tiles插件的类名是TilesPlugin而不是TilesPlugIn,与Validator不同。