PreparedStatement 偶然遇到问题

最近做了个项目。。测了好几遍了。。。然后突然测试那边的数据库环境执行一条SQL语句不行了。报错“ java.net.SocketException: Connection reset”
SQL语句为(

select ID as id,collageID as collageId,parentID as parentId ,orgName as orgName
from collage_orgGroups where ID IN(SELECT ID FROM dbo.F_GetChildren(?))
)其中F_GetChildren是一个函数,传个父节点的ID值返回所有全递归子节点。这sql语句绝对没问题,在本地和测试的查询分析器里执行是正常的。然后在本机测试了程序下可以。其他开发部门同事机子上也可以。就测试部门不可以。我把本地库分离下来附加到测试那边的环境。还是不行。我的猜测就是测试那边数据库环境出现错误了。。。但是却不知道是哪出错了。。。正要放弃时突然发现我如果不用PreparedStatement的预编译
pst.setInt(1,1);
直接拼接sql语句
select ID as id,collageID as collageId,parentID as parentId ,orgName as orgName from collage_orgGroups where ID IN(SELECT ID FROM dbo.F_GetChildren(1))
就可以。。。。很奇怪。。网上找了很多资料。但是没个准确的解释。希望大家知道了。。说声。。。。
问题补充
抛出异常的爱 写道
连接未关闭。
建议使用组件

抛哥不是吧。。。我贴下完整代码
public static void main(String[] args) throws IOException {
Connection conn=null;
PreparedStatement pst=null;
ResultSet rs=null;
try {
conn=getConnByParam("192.168.0.102", "sa", "123", "NewsDBTest");
System.out.println(conn);
String sql="select ID as id,collageID as collageId,parentID as parentId ,orgName as orgName"
+" from collage_orgGroups where ID IN(SELECT ID FROM dbo.F_GetChildren(?))";
pst=conn.prepareStatement(sql);
pst.setInt(1,1);
rs=pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("id")+"---"+rs.getString("orgName")+"---"+rs.getString("parentId"));
}
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        try {
            if(conn!=null){
                conn.close();
            }
            if(pst!=null){
                pst.close();
            }
            if(rs!=null){
                rs.close();
            }
        } catch (Exception e) {
        }
    }

}</pre><br /><br />异常:<pre name="code" class="java">java.sql.SQLException: I/O Error: Connection reset by peer: socket write error
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1053)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:465)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:776)
at cn.com.shanli.collageNews.business.utils.CommUtils.main(CommUtils.java:164)

Caused by: java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.DataOutputStream.write(DataOutputStream.java:90)
at net.sourceforge.jtds.jdbc.SharedSocket.sendNetPacket(SharedSocket.java:676)
at net.sourceforge.jtds.jdbc.RequestStream.putPacket(RequestStream.java:560)
at net.sourceforge.jtds.jdbc.RequestStream.flush(RequestStream.java:508)
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1040)
... 3 more



如果我屏蔽掉 pst.setInt(1,1);然后把sql语句中的问号改成1,就可以了。。。难道是我函数原因。但是在我和我同事机子上也可以啊。
函数语句:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[F_GetChildren]') AND xtype in (N'FN', N'IF', N'TF'))
BEGIN
execute dbo.sp_executesql @statement = N'Create Function [dbo].F_GetChildren
Returns @Tree Table (ID Int)
As
Begin
Insert @Tree Select ID From collage_orgGroups Where parentID = @Pid

While @@Rowcount > 0
Insert @Tree Select A.ID From collage_orgGroups A Inner Join @Tree B On A.ParentID = B.ID And A.ID Not In (Select ID From @Tree)
Return
End
'
END

①:服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;

Oracle的并发数是否有关?去调一下数据库参数吧

连接未关闭。
建议使用组件

[quote]Connection reset by peer的原因:
经常出现的Connection reset by peer: 原因可能是多方面的,不过更常见的原因是:
①:服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;
②:客户关掉了浏览器,而服务器还在给客户端发送数据;
③:浏览器端按了Stop [/quote]

[code="java"] try {

if(conn!=null){

conn.close();

}

if(pst!=null){

pst.close();

}

if(rs!=null){

rs.close();

}
[/code]
把这个反过来关 试试。

为什么不用框架作这东西
手写jdbc好多好多年没见过了。

首先,使用用框架(自己写的或者像springframework等已有的),这样对错误处理,等等但又有好处,而且一致处理,不会有遗漏,……,好处就不一一列举了。
其次,检查下你的jdbc驱动程序,看看使用的版本是什么,大不了跟踪进去看看,这个是比较诡异的。
其次,尽量不要写:
String sql="select ID as id,collageID as collageId,parentID as parentId ,orgName as orgName"

+" from collage_orgGroups where ID IN(SELECT ID FROM dbo.F_GetChildren(?))";

用一个stringbuilder到string的转换,既是可读性高,又性能好,总而言之,还是少些sql的比较好,特别是使用plsql函数。如果只是测试,那还可以。
再看看你的网络设置吧,具体没有跟踪,只能提供一点参考意见。

另外,再看看你使用的connection关闭是不是硬关闭,如果一个环境是,一个不是,也可能出现。
或者是不是打开的链接受到限制了,在你的机器上。

貌似是关闭连接的时候有问题

[quote="redhat"]首先,使用用框架(自己写的或者像springframework等已有的),这样对错误处理,等等但又有好处,而且一致处理,不会有遗漏,……,好处就不一一列举了。
其次,检查下你的jdbc驱动程序,看看使用的版本是什么,大不了跟踪进去看看,这个是比较诡异的。
其次,尽量不要写:
String sql="select ID as id,collageID as collageId,parentID as parentId ,orgName as orgName"

+" from collage_orgGroups where ID IN(SELECT ID FROM dbo.F_GetChildren(?))";

用一个stringbuilder到string的转换,既是可读性高,又性能好,总而言之,还是少些sql的比较好,特别是使用plsql函数。如果只是测试,那还可以。
再看看你的网络设置吧,具体没有跟踪,只能提供一点参考意见。[/quote]

呵呵,没下文了啊。

  • [b]对于这个sql语句使用"+"拼接的可读性更好(实际上还是stringbuilder)[/b]

  • 不象是 连接已经满了的问题。

  • 不过确实诡异,跟踪调试下吧!
    文中提到:
    at cn.com.shanli.collageNews.business.utils.CommUtils.main(CommUtils.java:164)
    怎么没给出CommUtils.java:164的代码。

at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:776)
猜测是此句:rs=pst.executeQuery(); 产生的异常,如果是的,那么也不是链接突然断开的问题。

  • 如果是rs=pst.executeQuery(); 产生的异常,那还没有到链接关闭的执行。虽然链接关闭顺序确实搞反了。
    [quote="jyjava"]貌似是关闭连接的时候有问题[/quote]

  • bug的可能性?

尝试:
pst.execute();
rs = pst.getResultSet();

什么啊 是那个问号的问题,那个问号貌似不能写到函数参数上。。。。。

建议核实下数据库和驱动的版本!

if(conn!=null){

conn.close();

}

if(pst!=null){

pst.close();

}

if(rs!=null){

rs.close();

} 这里也要改一下,要反过来

[quote="cnzxp521"]if(conn!=null){

conn.close();

}

if(pst!=null){

pst.close();

}

if(rs!=null){

rs.close();

} 这里也要改一下,要反过来[/quote]
顺序都不对
反了!~~~

[code="java"]public static void main(String[] args) finally{
try {
if(conn!=null){
conn.close();
}
if(pst!=null){
pst.close();
}
if(rs!=null){
rs.close();
}
} catch (Exception e) {
}
}

}[/code]

只需要conn.close();就可以了,关闭Connection会关闭该连接下资源

  • 对于这个sql语句使用"+"拼接的可读性更好(实际上还是stringbuilder),

用stringbuilder,特别是希望转换成string 变成final的,即这句,用一个stringbuilder到string的转换。

你用的是数据库的函数,然后你在java中给它赋值,有可能是并发的问题,对与这个问题,建议sql中的参数的传参不要使用“?”号,和什么stringbuilder毛关系没有。

显示是连接未关闭,建议使用组件。关闭下再试试