你的位置:首页 > Java教程

[Java教程]jdbc中的Statement对象和Preparedstatement对象的区别,以及通过jdbc操作调用存储过程


一、

java.sql.*   和  javax.sql.*的包的类结构

 

                            |- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。

                                     |- connect(url, properties):  连接数据库的方法。

                                                        url: 连接数据库的URL

                                                                 URL语法: jdbc协议:数据库子协议://主机:端口/数据库

                                                                 user: 数据库的用户名

                                                                 password: 数据库用户密码

                            |- DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序

                                     |-registerDriver(driver)  : 注册驱动类对象

                                     |-Connection getConnection(url,user,password);  获取连接对象

 

                            |- Connection接口: 表示java程序和数据库的连接对象。

                                               |- Statement createStatement() : 创建Statement对象

                                               |- PreparedStatement prepareStatement(String sql)  创建PreparedStatement对象

                                               |- CallableStatement prepareCall(String sql) 创建CallableStatement对象

 

                            |- Statement接口: 用于执行静态的sql语句

                                               |- int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)

                                               |- ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)

 

                                     |-PreparedStatement接口:用于执行预编译sql语句

                                                        |- int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)

                                                        |-ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)

 

                                               |-CallableStatement接口:用于执行存储过程的sql语句(call xxx)

                                                                 |-ResultSet executeQuery()  : 调用存储过程的方法

 

 

                            |- ResultSet接口:用于封装查询出来的数据

                                               |- boolean next() : 将光标移动到下一行

                                               |-getXX() : 获取列的值

Statemetent对象执行的是静态SQL语句,而PreparedStatement对象执行的是预编译SQL语句,如上图,Statement对象执行executeUpdate(String sql)和executeQuery(String sql),而PreparedStatement 对象执行的是无参的executeUpdate()和executeQuery(),从这两个方法可以看出这两个对象的特点,正因为如此,PreparedStatement可以预防SQL语句注入,更安全,当然它的效率也更高一些。

二、通过jdbc代码调用存储过程

代码如下

              

package com.a_callrablestatement;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.junit.Test;

import com.util.DBUtil;

public class Demo1 {

public Connection conn = null;
public CallableStatement cs = null;
ResultSet rs = null;
String driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
String url = "jdbc:sqlserver://localhost:1433;DatabaseName=User";
String username = "sa";
String password = "qwer1234";
String sql = "exec pro_findById ? ";
public Demo1() {
// TODO Auto-generated constructor stub
}
@Test
public void test1()
{

try{
//注册驱动
Class.forName(driverClass);
//连接
conn = DriverManager.getConnection(url,username,password);
//得到prepareCall预编译对象
cs = conn.prepareCall(sql);
//设置问号的占位符
cs.setInt(1,3);

rs = cs.executeQuery();
//打印结果
while(rs.next())
{
int id = rs.getInt("id");
String name = rs.getString("username");
String password = rs.getString("password");
String gender = rs.getString("gender");
String interest = rs.getString("interest");
System.out.println(id+","+name+","+password+","+gender+","+interest);
}
}catch(ClassNotFoundException e)
{
e.printStackTrace();
}catch(SQLException e)
{
e.printStackTrace();
}finally
{
DBUtil.close(conn,rs,cs);
}
}

@Test
public void test2()
{
sql ="exec pro_findNameById ?,?";
try{
//注册驱动
Class.forName(driverClass);
//连接
conn = DriverManager.getConnection(url,username,password);
//得到prepareCall预编译对象
cs = conn.prepareCall(sql);
//设置问号的占位符的参数值
cs.setInt(1,3);
/**
* 1.参数一,表示要设置的参数位置
* 2.参数二,表示要返回的参数值类型 varchar(20)
*/
cs.registerOutParameter(2, Types.VARCHAR);
//执行操作,但不返回结果集,返回值在参数中,这里只能用execute(),不能用executeQuery(),这是在SQL Server2008中
cs.execute();

/**
* 预编译sql中参数的位置
*/
String name = cs.getString(2);
//打印结果
System.out.println(name);


}catch(ClassNotFoundException e)
{
e.printStackTrace();
}catch(SQLException e)
{
e.printStackTrace();
}finally
{
DBUtil.close(conn,rs,cs);
}
}

}

工具类

package com.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {

public DBUtil() {
// TODO Auto-generated constructor stub
}
public static void close(Connection conn,ResultSet rs,PreparedStatement ps )
{
try{
if(conn!=null)
{
conn.close();
}
if(rs!=null)
{
rs.close();
}
if(ps!=null)
{
ps.close();
}
}catch(SQLException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

1.test1()方法是调用没有返回值的存储过程

2,test2()方法是调用有返回值的存储过程

在调用有返回值的存储过程时,不能使用executeQuery(),否则会报没有返回结果集的错误

而改为execute()方法后就可以得到正常的结果

test1()中的存储过程代码

use [User]
go

create procedure pro_findById(@id int)
as
select * from [tb_user] where id=@id
go

 

test2()中的存储过程

use [User]
go
create procedure findNameById @id int,@name varchar(20)
as
select @name=username from tb_user where id=@id
go

注:SQL server 2008和jdk 1.7 加eclipse ee 4.5