Java中调用SQL Server存储过程详解

 更新时间:2015年01月15日 11:38:35   投稿:junjie  
这篇文章主要介绍了Java中调用SQL Server存储过程详解,本文讲解了使用不带参数的存储过程、使用带有输入参数的存储过程、使用带有输出参数的存储过程、使用带有返回状态的存储过程、使用带有更新计数的存储过程等操作实例,需要的朋友可以参考下

本文作者介绍了通过Java如何去调用SQL Server的存储过程,详解了5种不同的存储。详细请看下文

1、使用不带参数的存储过程

使用 JDBC 驱动程序调用不带参数的存储过程时,必须使用 call SQL 转义序列。不带参数的 call 转义序列的语法如下所示:

复制代码 代码如下:

{call procedure-name}

作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:
复制代码 代码如下:

CREATE PROCEDURE GetContactFormalNames 
AS
BEGIN
 SELECT TOP 10 Title + ' ' + FirstName + ' ' + LastName AS FormalName 
 FROM Person.Contact 
END

此存储过程返回单个结果集,其中包含一列数据(由 Person.Contact 表中前十个联系人的称呼、名称和姓氏组成)。

在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 executeQuery 方法调用 GetContactFormalNames 存储过程。

复制代码 代码如下:

public static void executeSprocNoParams(Connection con) ...{ 
 try ...{ 
 Statement stmt = con.createStatement(); 
ResultSet rs = stmt.executeQuery("{call dbo.GetContactFormalNames}"); 

 while (rs.next()) ...{ 
 System.out.println(rs.getString("FormalName")); 

rs.close(); 
stmt.close(); 
  } 
catch (Exception e) ...{ 
e.printStackTrace(); 

}


2、使用带有输入参数的存储过程

使用 JDBC 驱动程序调用带参数的存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 IN 参数的 call 转义序列的语法如下所示:

复制代码 代码如下:

{call procedure-name[([parameter][,[parameter]]...)]}

构造 call 转义序列时,请使用 ?(问号)字符来指定 IN 参数。此字符充当要传递给该存储过程的参数值的占位符。可以使用 SQLServerPreparedStatement 类的 setter 方法之一为参数指定值。可使用的 setter 方法由 IN 参数的数据类型决定。

向 setter 方法传递值时,不仅需要指定要在参数中使用的实际值,还必须指定参数在存储过程中的序数位置。例如,如果存储过程包含单个 IN 参数,则其序数值为 1。如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

作为如何调用包含 IN 参数的存储过程的实例,使用 SQL Server 2005 AdventureWorks 示例数据库中的 uspGetEmployeeManagers 存储过程。此存储过程接受名为 EmployeeID 的单个输入参数(它是一个整数值),然后基于指定的 EmployeeID 返回雇员及其经理的递归列表。下面是调用此存储过程的 Java 代码:

复制代码 代码如下:

public static void executeSprocInParams(Connection con) ...{ 
 try ...{ 
 PreparedStatement pstmt = con.prepareStatement("{call dbo.uspGetEmployeeManagers(?)}"); 
 pstmt.setInt(1, 50); 
 ResultSet rs = pstmt.executeQuery(); 
 while (rs.next()) ...{ 
 System.out.println("EMPLOYEE:"); 
 System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName")); 
 System.out.println("MANAGER:"); 
 System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName")); 
 System.out.println(); 
 } 
 rs.close(); 
 pstmt.close(); 
 } 
 catch (Exception e) ...{ 
 e.printStackTrace(); 
 } 
}

3、使用带有输出参数的存储过程

使用 JDBC 驱动程序调用此类存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。带有 OUT 参数的 call 转义序列的语法如下所示:

复制代码 代码如下:

{call procedure-name[([parameter][,[parameter]]...)]}

构造 call 转义序列时,请使用 ?(问号)字符来指定 OUT 参数。此字符充当要从该存储过程返回的参数值的占位符。要为 OUT 参数指定值,必须在运行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定各参数的数据类型。

使用 registerOutParameter 方法为 OUT 参数指定的值必须是 java.sql.Types 所包含的 JDBC 数据类型之一,而它又被映射成本地 SQL Server 数据类型之一。有关 JDBC 和 SQL Server 数据类型的详细信息,请参阅了解 JDBC 驱动程序数据类型。

当您对于 OUT 参数向 registerOutParameter 方法传递一个值时,不仅必须指定要用于此参数的数据类型,而且必须在存储过程中指定此参数的序号位置或此参数的名称。例如,如果存储过程包含单个 OUT 参数,则其序数值为 1;如果存储过程包含两个参数,则第一个序数值为 1,第二个序数值为 2。

作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程: 根据指定的整数 IN 参数 (employeeID),该存储过程也返回单个整数 OUT 参数 (managerID)。根据 HumanResources.Employee 表中包含的 EmployeeID,OUT 参数中返回的值为 ManagerID。

在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 GetImmediateManager 存储过程:

复制代码 代码如下:

public static void executeStoredProcedure(Connection con) ...{ 
 try ...{ 
 CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}"); 
 cstmt.setInt(1, 5); 
 cstmt.registerOutParameter(2, java.sql.Types.INTEGER); 
 cstmt.execute(); 
 System.out.println("MANAGER ID: " + cstmt.getInt(2)); 
 } 
 catch (Exception e) ...{ 
 e.printStackTrace(); 
 } 
}

本示例使用序号位置来标识参数。或者,也可以使用参数的名称(而非其序号位置)来标识此参数。下面的代码示例修改了上一个示例,以说明如何在 Java 应用程序中使用命名参数。请注意,这些参数名称对应于存储过程的定义中的参数名称: 11x16CREATE PROCEDURE GetImmediateManager
复制代码 代码如下:

@employeeID INT, 
 @managerID INT OUTPUT
AS
BEGIN
 SELECT @managerID = ManagerID 
 FROM HumanResources.Employee 
 WHERE EmployeeID = @employeeID 
END

存储过程可能返回更新计数和多个结果集。Microsoft SQL Server 2005 JDBC Driver 遵循 JDBC 3.0 规范,此规范规定在检索 OUT 参数之前应检索多个结果集和更新计数。也就是说,应用程序应先检索所有 ResultSet 对象和更新计数,然后使用 CallableStatement.getter 方法检索 OUT 参数。否则,当检索 OUT 参数时,尚未检索的 ResultSet 对象和更新计数将丢失。

4、使用带有返回状态的存储过程

使用 JDBC 驱动程序调用这种存储过程时,必须结合 SQLServerConnection 类的 prepareCall 方法使用 call SQL 转义序列。返回状态参数的 call 转义序列的语法如下所示:

复制代码 代码如下:

{[?=]call procedure-name[([parameter][,[parameter]]...)]}

构造 call 转义序列时,请使用 ?(问号)字符来指定返回状态参数。此字符充当要从该存储过程返回的参数值的占位符。要为返回状态参数指定值,必须在执行存储过程前使用 SQLServerCallableStatement 类的 registerOutParameter 方法指定参数的数据类型。

此外,向 registerOutParameter 方法传递返回状态参数值时,不仅需要指定要使用的参数的数据类型,还必须指定参数在存储过程中的序数位置。对于返回状态参数,其序数位置始终为 1,这是因为它始终是调用存储过程时的第一个参数。尽管 SQLServerCallableStatement 类支持使用参数的名称来指示特定参数,但您只能对返回状态参数使用参数的序号位置编号。

作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:

复制代码 代码如下:

CREATE PROCEDURE CheckContactCity 
 (@cityName CHAR(50)) 
AS
BEGIN
 IF ((SELECT COUNT(*) 
 FROM Person.Address 
 WHERE City = @cityName) > 1) 
 RETURN 1 
ELSE
 RETURN 0 
END

该存储过程返回状态值 1 或 0,这取决于是否能在表 Person.Address 中找到 cityName 参数指定的城市。

在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,然后使用 execute 方法调用 CheckContactCity 存储过程:

复制代码 代码如下:

public static void executeStoredProcedure(Connection con) ...{ 
 try ...{ 
 CallableStatement cstmt = con.prepareCall("{? = call dbo.CheckContactCity(?)}"); 
 cstmt.registerOutParameter(1, java.sql.Types.INTEGER); 
 cstmt.setString(2, "Atlanta"); 
 cstmt.execute(); 
 System.out.println("RETURN STATUS: " + cstmt.getInt(1)); 
 } 
 cstmt.close(); 
 catch (Exception e) ...{ 
 e.printStackTrace(); 
 } 
}

5、使用带有更新计数的存储过程

使用 SQLServerCallableStatement 类构建对存储过程的调用之后,可以使用 execute 或 executeUpdate 方法中的任意一个来调用此存储过程。executeUpdate 方法将返回一个 int 值,该值包含受此存储过程影响的行数,但 execute 方法不返回此值。如果使用 execute 方法,并且希望获得受影响的行数计数,则可以在运行存储过程后调用 getUpdateCount 方法。

作为实例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下表和存储过程:

复制代码 代码如下:

CREATE TABLE TestTable 
 (Col1 int IDENTITY, 
 Col2 varchar(50), 
 Col3 int); 

CREATE PROCEDURE UpdateTestTable 
 @Col2 varchar(50), 
 @Col3 int
AS
BEGIN
 UPDATE TestTable 
 SET Col2 = @Col2, Col3 = @Col3 
END;


在下面的实例中,将向此函数传递 AdventureWorks 示例数据库的打开连接,并使用 execute 方法调用 UpdateTestTable 存储过程,然后使用 getUpdateCount 方法返回受存储过程影响的行计数。
复制代码 代码如下:

public static void executeUpdateStoredProcedure(Connection con) ...{ 
 try ...{ 
 CallableStatement cstmt = con.prepareCall("{call dbo.UpdateTestTable(?, ?)}"); 
 cstmt.setString(1, "A"); 
 cstmt.setInt(2, 100); 
 cstmt.execute(); 
 int count = cstmt.getUpdateCount(); 
 cstmt.close(); 

 System.out.println("ROWS AFFECTED: " + count); 
 } 
 catch (Exception e) ...{ 
 e.printStackTrace();

相关文章

  • SpringBoot内部外部配置文件加载顺序解析

    SpringBoot内部外部配置文件加载顺序解析

    这篇文章主要介绍了SpringBoot内部外部配置文件加载顺序解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • SpringBoot之@Value获取application.properties配置无效的解决

    SpringBoot之@Value获取application.properties配置无效的解决

    这篇文章主要介绍了SpringBoot之@Value获取application.properties配置无效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java并发编程之Semaphore详解

    Java并发编程之Semaphore详解

    这篇文章主要介绍了Java并发编程之concurrent包中的Semaphore详解,信号量Semaphore一般用来表示可用资源的个数,相当于一个计数器,可类比生活中停车场牌子上面显示的停车场剩余车位数量,需要的朋友可以参考下
    2023-12-12
  • JavaWeb中的Cookie和Session解读

    JavaWeb中的Cookie和Session解读

    这篇文章主要介绍了JavaWeb中的Cookie和Session解读,Cookie是servlet发送到Web浏览器的少量信息,该信息由浏览器保存,然后发送回服务器,一般情况下,Cookie是以键值对进行表示的,Cookie的值可以唯一地标识客户端,因此Cookie常用于会话管理,需要的朋友可以参考下
    2023-10-10
  • java中ResultSet遍历数据操作

    java中ResultSet遍历数据操作

    这篇文章主要介绍了java中ResultSet遍历数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • SpringBoot整合SpringSecurity实现JWT认证的项目实践

    SpringBoot整合SpringSecurity实现JWT认证的项目实践

    本文会通过创建SpringBoot项目整合SpringSecurity,实现完整的JWT认证机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • java实现猜拳小游戏

    java实现猜拳小游戏

    这篇文章主要为大家详细介绍了java实现猜拳小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • Java @Transactional指定回滚条件

    Java @Transactional指定回滚条件

    这篇文章主要介绍了Java @Transactional指定回滚条件,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • 详解Springboot自定义异常处理

    详解Springboot自定义异常处理

    本篇文章主要介绍了详解Springboot自定义异常处理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 关于intellij idea打开就闪退或关闭详细解决办法

    关于intellij idea打开就闪退或关闭详细解决办法

    这篇文章主要介绍了关于intellij idea打开就闪退或关闭详细解决办法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03

最新评论