一、为什么用PreparedStatement而不用Statement?
1. PreparedStatement 继承于 Statement,所以更完善于Statement ;
2. PreparedStatement 已经 预编译 过 ,所以执行速度要比Statement快,效率高;
3. PreparedStatement 安全性好,有效防止SQL注入。
(说到这个,看到一句话刺激到我了,“稍有水平的开发者就会使用PreparedStatement而不用Statement”,想起我大二时还屁颠屁颠的用了Statement快一年,后来和同学一块学习黑客技术时,学了一点SQL注入,当时我做了一个简单的JSP,用的就是Statement,没想到这个JSP被我们一句简单的SQL语句就攻破了,很是尴尬!由此才知到PreparedStatement是那么好。)
二、 CallableStatement是干嘛的?
答: CallableStatement用于执行 SQL 存储过程的接口,继承于PreparedStatement;
使用之前一定要在数据库中建有已知的存储过程;
在执行存储过程之前,必须注册所有 OUT 参数的类型;它们的值是在执行后通过此类提供的 get 方法获取的;
CallableStatement 可以返回一个 ResultSet 对象或多个 ResultSet 对象。多个 ResultSet 对象是使用继承自 Statement 的操作处理的;
为了获得最大的可移植性,调用的 ResultSet 对象和更新计数应该在获得输出参数的值之前处理。
三、在Connection上调用close方法会关闭Statement和ResultSet 吗?
答:一般情况下使用到数据库一定会用到数据库连接池,所以当调用Connection的close方法时,并不是物理关闭,而是将其归还到连接池中,所以Statement和ResultSet 可能依然被持有,并且实际占用相关的数据库的游标资源,在这种情况下,只要长期运行就有可能报“游标超出数据库允许的最大值”的错误,导致程序无法正常访问数据库。所以为了充分利用数据库的资源,最好的关闭顺序为:rs.close(); stm.close(); con.close();
查询这三者的API得知,
Connection.close() 立即释放此 Connection
对象的数据库和 JDBC 资源,而不是等待它们被自动释放。
Statement.close()立即释放此 Statement
对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作。一般来说,使用完后立即释放资源是一个好习惯,这样可以避免对数据库资源的占用。
注:关闭 Statement
对象时,还将同时关闭其当前的 ResultSet
对象(如果有)。
ResultSet.close()立即释放此 ResultSet
对象的数据库和JDBC资源,而不是等待该对象自动关闭时发生此操作。
四、简单测试代码如下:
package com.wang.db;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
*
* @ClassName: OracleJDBC
* @Description: TODO
* @author 王清飞(WangQingFei)
* @date 2015年8月17日 下午6:09:48
*/
public class OracleJDBC {
public static void main(String[] args) {
TestJDBC();
}
public static void TestJDBC() {
CallableStatement proc = null;
Connection con = null;// 创建一个数据库连接
PreparedStatement pre = null;
ResultSet result = null;// 创建一个结果集对象
try
{
//三个参数可以在Oracle客户端的文件夹里查到
//D:\PLSQL Developer 9.0.0.1601破解\instantclient_11_2\network\admin\tnsnames.ora文件里可以查到
String HOST="*.*.*.*"; //服务器地址
String PORT="1521";
String SERVICE_NAME="ORCL";
String url = "jdbc:oracle:thin:@"+HOST+":"+PORT+":"+SERVICE_NAME;
String user = "skywang";// 用户名
String password = "skywang";// 密码
Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序
System.out.println("====================正在连接数据库!=========================");
con = DriverManager.getConnection(url, user, password);// 获取连接
//===================调用存储过程进行数据库查询=========================================
//存储过程在数据库要创建好,知道具体作用
// proc= con.prepareCall("{call getTableCount(?,?)}"); //调用存储过程
// proc.setString(1, "DEPARTMENT"); //传入参数
// proc.registerOutParameter(2, Types.INTEGER); //注册输出参数类型
// proc.execute(); //执行
// System.out.println(proc.getString(2)); //取出参数
System.out.println("=====================数据库连接成功!=======================");
String sql = "select * from student where id=?";// 预编译语句
pre = con.prepareStatement(sql);// 实例化预编译语句
pre.setInt(1, 10);// 设置参数
result = pre.executeQuery();// 执行查询
while (result.next()) // 遍历结果集
System.out.println("姓名:" + result.getString("name"));
}
catch (Exception e)
{
e.printStackTrace();
}
finally //无论程序如何都要执行
{
try
{
// 将上面的几个对象关闭,不关闭的话会影响性能、并且占用资源
if (result != null)
result.close();
if (pre != null)//当生成 ResultSet 对象的 Statement 对象关闭、重新执行或用来从多个结果的序列获取下一个结果时, 该 Statement 对象将自动关闭 ResultSet 对象。
pre.close();
if (con != null)
con.close();
System.out.println("================数据库连接已关闭!====================");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}