详细学习之java简单连接Oracle数据库

时间:2021-07-01 07:45:33

一、为什么用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();
       }
   }

}
}