? ? ? ?CallableStatement 对象为所有的DBMS 提供了一种以标准形式调用已储存过程的方法。已储 存过程储存在数据库中。对已储存过程的调用是 CallableStatement对象所含的内容。这种调用是 用一种换码语法来写的,有两种形式:一种形式带结果参,另一种形式不带结果参数。结果参数是 一种输出 (OUT) 参数,是已储存过程的返回值。两种形式都可带有数量可变的输入(IN 参数)、 输出(OUT 参数)或输入和输出(INOUT 参数)的参数。问号将用作参数的占位符。
1.带?参数的使用prepareStatement。这也是使用最多的。
?
public void addCategory(Category category) { String sql = "insert into category values(seque_cid.nextval,?,?)"; PreparedStatement pstmt = null; try { pstmt = conn.prepareStatement(sql); pstmt.setString(1, category.getCname()); pstmt.setString(2, category.getCdesc()); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally{ //关闭 if(pstmt!=null){ try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
?2.不带参数,例如查所用,不需要到任何参数。使用statement。
?
?
public List<Category> getAllCategorys() { List<Category>list = new ArrayList<Category>(); String sql = "select * from category "; Category c = null; Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while(rs.next()){ c = new Category(); c.setCid(rs.getInt(1)); c.setCname(rs.getString(2)); c.setCdesc(rs.getString(3)); list.add(c); } } catch (SQLException e) { e.printStackTrace(); }finally{ //关闭 if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; }
?3.调用存储过程的CallableStatement。
?
特别注意,存储过程的输出参数需要先进行注册。
public void callProcedure() { String sql = "{call proce_bigger(?,?,?,?)}"; CallableStatement cstmt = null; try { cstmt = conn.prepareCall(sql); cstmt.setInt(1, 10); cstmt.setInt(2, 13); cstmt.registerOutParameter(3, Types.INTEGER); cstmt.registerOutParameter(4, Types.INTEGER); cstmt.setInt(4, 6); cstmt.executeUpdate(); System.out.println(cstmt.getInt(3)); System.out.println(cstmt.getInt(4)); } catch (Exception e) { e.printStackTrace(); }finally{ //关闭 if(cstmt!=null){ try { cstmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
?1 ?使用不带参数的存储过程?
?
public static void executeStoredProcedure(Connection con) { try { CallableStatementcstmt = con .prepareCall("{calldbo.GetContactFormalNames}"); ResultSetrs = cstmt.executeQuery(); while (rs.next()) { System.out.println(rs.getString("FormalName")); } } catch (Exception e) { e.printStackTrace(); } finally { rs.close(); cstmt.close(); } }?
?
2 使用带有输入参数的存储过程?
?
public static void executeStoredProcedure(Connection con) { try { CallableStatementcstmt = con .prepareCall("{call dbo.uspGetEmployeeManagers(?)}"); cstmt.setInt(1, 50); ResultSetrs = cstmt.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(); } } catch (Exception e) { e.printStackTrace(); } finally { rs.close(); cstmt.close(); } }?
?
3 使用带有输出参数的存储过程?
?
public static void executeStoredProcedure(Connection con) { try { CallableStatementcstmt = 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(); } }?
?
4 使用带有返回状态的存储过程(目前测试状态返回只能是int类型)?
作为示例,在 SQL Server 2005 AdventureWorks 示例数据库中创建以下存储过程:?
?
CREATE PROCEDURE CheckContactCity @cityNameCHAR(50)ASBEGIN IF ((SELECT COUNT(*) FROM Person.Address WHERE City = @cityName) > 1) RETURN 1ELSE RETURN 0END?
?
?
public static void executeStoredProcedure(Connection con) { try { CallableStatementcstmt = 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)); } catch (Exception e) { e.printStackTrace(); }finally{ cstmt.close(); } }?
?
注:在sql中执行该存储过程的方法: declare @c int?
exec @c=CheckContactCity 'Atlanta' print @c?
5 使用带有更新记数的存储过程?
作为示例,在 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;
?
public static void executeUpdateStoredProcedure(Connection con) { try { CallableStatementcstmt = con .prepareCall("{call dbo.UpdateTestTable(?, ?)}"); cstmt.setString(1, "A"); cstmt.setInt(2, 100); cstmt.execute(); int count = cstmt.getUpdateCount(); System.out.println("ROWS AFFECTED: " + count); } catch (Exception e) { e.printStackTrace(); }finally{ cstmt.close(); } }
?
??
附加说明?
?
JDBC调用存储过程: CallableStatement?
在Java里面调用存储过程,写法那是相当的固定: Class.forName(....?
Connection conn = DriverManager.getConnection(.... /**?
*p是要调用的存储过程的名字,存储过程的4个参数,用4个?号占位符代替 *其余地方写法固定 */?
CallableStatementcstmt = conn.prepareCall("{call p(?,?,?,?)}"); /**?
*告诉JDBC,这些个参数,哪些是输出参数,输出参数的类型用java.sql.Types来指定?
*下面的意思是,第3个?和第4个?是输出参数,类型是INTEGER的 *Types后面具体写什么类型,得看你的存储过程参数怎么定义的?
*/?
cstmt.registerOutParameter(3, Types.INTEGER); cstmt.registerOutParameter(4, Types.INTEGER); /**?
*在我这里第1个?和第2个?是输入参数,第3个是输出参数,第4个既输入又输出?
*下面是设置他们的值,第一个设为3,第二个设为4,第4个设置为5 *没设第3个,因为它是输出参数 */?
cstmt.setInt(1, 3); cstmt.setInt(2, 4); cstmt.setInt(4, 5); //执行?
cstmt.execute();?
//把第3个参数的值当成int类型拿出来 int three = cstmt.getInt(3); System.out.println(three);?
//把第4个参数的值当成int类型拿出来 int four = cstmt.getInt(4); System.out.println(four);?
//用完别忘给人家关了,后开的先关 cstmt.close(); conn.close();?
JDBC调用存储过程,掌握这一个程序足够了.?
以下是上面程序使用的存储过程的代码,我用的是Oracle数据库,不过不论是什么数据库,对于你?
的程序,JDBC这一端写法都是一样的. create or replace procedure p?
? ? ? ? ? ? (v_a in number,v_bnumber,v_ret out number,v_temp in out number) is begin?
? ? ? ? ? ?if(v_a>v_b) then v_ret := v_a; ? ? ? ? ? ?else v_ret := v_b;?
? ? ? ? ? ?end if; v_temp := v_temp + 1; end;
?