显示标签为“LAZY LOAD”的博文。显示所有博文
显示标签为“LAZY LOAD”的博文。显示所有博文

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。