JDBC詳解

  • 2020 年 4 月 11 日
  • 筆記

1.概述

jdbc是什麼?

JDBC英文名為:

Java Data Base Connectivity(Java資料庫連接),從編程的角度來看,JDBC API是一組Java類和方法,它們允許將資料庫調用嵌入到伺服器應用程式中。更具體地說,JDBC規範是每個JDBC驅動程式供應商都必須實現的一組介面。驅動程式處理應用程式中的JDBC語句,並將它們包含的SQL參數路由到資料庫引擎

簡單說它就是JAVA與資料庫的連接的橋樑或者插件,用JAVA程式碼就能操作資料庫的增刪改查、存儲過程、事務等

該圖說明了應用程式組件如何使用JDBC與資料庫進行交互。

JDBC的結構如下圖

img

JDBC的作用

  • 載入對應資料庫驅動 (Load Driver)

  • 與資料庫建立連接(connection)

  • 發送 操作資料庫的語句(createStatement)

  • 執行並處理返回結果(executeQuery)

    這裡寫圖片描述

    1-1

他們的流程圖則是在下面

img

1-2

如上兩個圖可以十分清晰的看出來整個JDBC的運行方式.我們就一個一個的講解

載入對應資料庫驅動 (Load Driver)

這個部分是圖1-1的①部分,圖1-2的開始到Driver的那條線.

public static void main(String[] args) {  		// TODO Auto-generated method stub  		try {  			Class.forName("oracle.jdbc.OracleDriver");//顯式地載入 JDBC 驅動程式。  		} catch (ClassNotFoundException e) {  			e.printStackTrace();  		} // 創建連接得部分  	}  

到這裡你可能想問Class.forName("oracle.jdbc.OracleDriver")是啥.

這個就比較複雜,涉及到了反射相關的知識.在這裡簡述一下.(不看也沒啥,反正JDBC裡面把這句話背下來就行)


條子的拖堂時間

java是面向對象語言,最獨特的特點就是一切皆為對象.

但是對象還是有區別的,主要分為兩種.

一種是實例對象.(就是用new生成那個,你平時總用.)

一種則是Class對象(沒錯,就叫這個名字,首字母大寫.不是我神經失常又寫了一遍).

這個Class對象中包含的是每個類的運行時的類型資訊.所有與類有關的資訊全在裡面.

其實我們的實例對象就是靠Class對象來創建的.

每當編譯產生一個新類就產生一個Class對象.

可能你想問了,為什麼我平時沒見過這個Class對象?

這就對了,因為Class對象沒有公共的構造方法,Class對象實在類載入時由java虛擬機以及通過類載入器中的defineClass方法自動構建的.所以你是沒有辦法聲明Class對象的.

一個類載入到虛擬機需要以下三個步驟:

Class.forName("oracle.jdbc.OracleDriver");也是執行下面三個步驟.

  • 載入

    這是由類載入器(ClassLoader)執行的。通過一個類的全限定名來獲取其定義的二進位位元組流(Class位元組碼),將這個位元組流所代表的靜態存儲結構轉化為方法去的運行時數據介面,根據位元組碼在java堆中生成一個代表這個類的java.lang.Class對象。

  • 鏈接

    在鏈接階段將驗證Class文件中的位元組流包含的資訊是否符合當前虛擬機的要求,為靜態域分配存儲空間並設置類變數的初始值(默認的零值),並且如果必需的話,將常量池中的符號引用轉化為直接引用。

  • 初始化

    到了此階段,才真正開始執行類中定義的java程式程式碼。用於執行該類的靜態初始器和靜態初始塊,如果該類有父類的話,則優先對其父類進行初始化。(賦值也是此階段)

所有的類都是在對其第一次使用時,動態載入到JVM中的(懶載入)。當程式創建第一個對類的靜態成員的引用時,就會載入這個類

而我們的Class.forName("oracle.jdbc.OracleDriver");的作用就是載入這個類,並返回與帶有給定字元串名的類或介面相關聯的 Class 對象.

 2、類的初始化過程與類的實例化過程的異同?

  類的初始化是指類載入過程中的初始化階段對類變數按照程式猿的意圖進行賦值的過程;而類的實例化是指在類完全載入到記憶體中後創建對象的過程。

初始化和實例化的區別

其實你只要看過oracle.jdbc.OracleDriver源碼就知道,在其中有大量的靜態變數.

 public static final char slash_character = '/';      public static final char at_sign_character = '@';      public static final char left_square_bracket_character = '[';      public static final char right_square_bracket_character = ']';      public static final String oracle_string = "oracle";      public static final String protocol_string = "protocol";      public static final String user_string = "user";      public static final String password_string = "password";      public static final String database_string = "database";      public static final String server_string = "server";  //很多很多  

源碼

調用這個源碼後,這些個程式碼會被直接被賦值.

同時還有在網上找到一個博文,其中發現

Class.forName(driver)的根本目的就是為了調用DriverManager.registerDriver。

jdbc中的class.forName詳解

還有另外一篇博文,從mysql方面論證了這個情況,如下是MYSQL中的程式碼,可以看到也有一個同樣的static程式碼塊.

這個是圖1-1JDBCDriver到DriverManager的那條線,圖1-2 Driver到DriverManager那條線.

package com.mysql.jdbc    public class Driver extends NonRegisteringDriver implements java.sql.Driver {   // ~ Static fields/initializers   // --------------------------------------------- //   // Register ourselves with the DriverManager   //   static {      t ry {                java.sql.DriverManager.registerDriver(new Driver());//將Driver註冊給DriverManager            } catch (SQLException E) {                throw new RuntimeException("Can't register driver!");            }  //這個是圖1-1JDBCDriver到DriverManager的那條線,圖1-2Driver到DriverManager       /**      }  // ~ Constructors   // -----------------------------------------------------------  /**    * Construct a new driver and register it with DriverManager    *    * @throws SQLException    *             if a database error occurs.    */   public Driver() throws SQLException {       // Required for Class.forName().newInstance()   }  }  //從而通過Class.forName(DriverString)會向DriverManager註冊該Driver類.所以可以直接調用.而Class.forName("").newInstance()則等於是將該Driver驅動類實例化,返回該類的一個實例,所以,如果只是取JDBC的Driver驅動,可以不必用newInstance().  ————————————————  版權聲明:本文為CSDN部落客「jackterq」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。  原文鏈接:https://blog.csdn.net/jackterq/java/article/details/4480745      

你可能要問了為什麼這個直接載入了就行呢?不是要實例化才能調用其中的方法嗎(也未必哈).只是載入到JVM中有啥用啊!!

解釋就在下面:

如下是一段英文,講解了如下內容,就是跟你講,Driver只要註冊進虛擬機就ok了,沒必要生成實例.因為生成了實例你也用不到.    we just want to load the driver to jvm only, but not need to user the instance of driver, so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(), the result will same as calling Class.forName(xxx.xx.xx), because Class.forName(xxx.xx.xx).newInstance() will load driver first, and then create instance, but the instacne you will never use in usual, so you need not to create it.  ————————————————  版權聲明:本文為CSDN部落客「jackterq」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。  原文鏈接:https://blog.csdn.net/jackterq/java/article/details/4480745  

其實這也解釋了為什麼

當然,他用的版本應該是jdbc4之前的.

所以載入Class.forName("oracle.jdbc.OracleDriver")的作用可以稱之為為鏈接建立好準備,讓之後的DriverManager.getConnection("jdbc:oracle:thin:@192.168.80.10:1521:orcl","system","aA107824");有運行的基礎.

jdk6為什麼不需要 執行了Class.forName這行程式碼了呢,是怎麼回事?

大家先了解一下ServiceLoader 。

簡單來說就是在驅動jar包配置文件中,指定oracle.jdbc.driver.OracleDriver(驅動實例)實現java.sql.Driver介面;然後DriverManager在初始化的時候,自動掃描所有jar包中實現了java.sql.Driver的類 ,並初始化 此實現類

//DriverManager     static {          loadInitialDrivers();          println("JDBC DriverManager initialized");      }      private static void loadInitialDrivers() {         ...            AccessController.doPrivileged(new PrivilegedAction<Void>() {              public Void run() {                  //搜索服務的實現類(驅動實例)                  ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);                  Iterator<Driver> driversIterator = loadedDrivers.iterator();//這個明顯實現了Iterator介面,可以迭代.也就是搜索所有驅動.                  try{                      while(driversIterator.hasNext()) {                          driversIterator.next();// 此處初始化  並註冊了                      }                  } catch(Throwable t) {                  // Do nothing                  }                  return null;      //ServiceLoader         public S next() {              if (acc == null) {                  return nextService();              } else {          ...    //ServiceLoader         private S nextService() {              ...              try {                  c = Class.forName(cn, false, loader);//這個就是註冊驅動的程式碼.看看和我們前一個部分長得像不像              ...  

也就是說 DriverManger藉助 ServiceLoader 找到驅動 並註冊了,所以不需要再手工註冊

作者:氨基鈉
鏈接:https://www.jianshu.com/p/d0d646b2070c
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

ok廢話完了!


與資料庫建立連接(connection)

Connection connection=DriverManager.getConnection(      "jdbc:oracle:thin:@192.168.80.10:1521:orcl", //你的Oracle資料庫URL      // 192.168.80.10 這個部分改成你的資料庫地址或者localhost : 1521//這個是埠號 : orcl //這個是實例名      "system",//你的oracle資料庫帳號      "aA107824"//你的oracle資料庫密碼  );  

作為新手,你記住這部分就可以了.


條子的拖堂時間

DriverManager的一些理論知識

作為初始化的一部分,DriverManager 類會嘗試載入在 "jdbc.drivers" 系統屬性中引用的驅動程式類。      //這就是在上面那個拖堂時間講的oracle.jdbc.OracleDriver實際上是一個驅動程式,被直接註冊進DriverManger里,然後被DriverManger在初始化階段載入  這允許用戶自定義由他們的應用程式使用的 JDBC Driver.//沒錯你可以自己寫一個驅動程式    

DriverManager實現的功能

  • 連接功能

    你會發現實際上這個getConnection方法的主要執行部分在下面的private中,這也是一種很好的方法,可以保護自己的程式碼不被隨便的改動.

       public static Connection getConnection(String url)          throws SQLException {            java.util.Properties info = new java.util.Properties();//這個是讀取配置文件的類的實例          return (getConnection(url, info, Reflection.getCallerClass()));          //eflection.getCallerClass()可以得到調用者的類.這個方法是很好用的.      }        //  用於根據url、對應的屬性資訊在registeredDrivers中找到合適的註冊的驅動創建資料庫鏈接      private static Connection getConnection(          String url, java.util.Properties info, Class<?> caller) throws SQLException {          /*           * When callerCl is null, we should check the application's           * (which is invoking this class indirectly)           * classloader, so that the JDBC driver class outside rt.jar           * can be loaded from here.           */          //這個意思如果為空,就說明並沒有傳入一個類載入器,那麼就從執行緒上下獲取載入器          ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;          synchronized(DriverManager.class) {              // synchronize loading of the correct classloader.              if (callerCL == null) {                   //獲取執行緒上下文類載入器                  callerCL = Thread.currentThread().getContextClassLoader();                }          }  //url沒輸入,報錯          if(url == null) {              throw new SQLException("The url cannot be null", "08001");          }            println("DriverManager.getConnection("" + url + "")");            // Walk through the loaded registeredDrivers attempting to make a connection.          // Remember the first exception that gets raised so we can reraise it.          SQLException reason = null;            for(DriverInfo aDriver : registeredDrivers) {              // If the caller does not have permission to load the driver then              // skip it.           //一個應用中有可能會有多個資料庫驅動,需要判斷資料庫連接的調用者(調用getConnection()方法的對象)是否與驅動相匹配(別讓Oracle調用了mysql的驅動)              if(isDriverAllowed(aDriver.driver, callerCL)) {                  try {                      println("    trying " + aDriver.driver.getClass().getName());                      Connection con = aDriver.driver.connect(url, info);                      if (con != null) {                          // Success!                          println("getConnection returning " + aDriver.driver.getClass().getName());                          return (con);                      }                  } catch (SQLException ex) {                      if (reason == null) {                          reason = ex;                      }                  }                } else {                  println("    skipping: " + aDriver.getClass().getName());              }            }            // if we got here nobody could connect.          if (reason != null)    {              println("getConnection failed: " + reason);              throw reason;          }            println("getConnection: no suitable driver found for "+ url);          throw new SQLException("No suitable driver found for "+ url, "08001");      }  }  

    如下這個內容是判斷,你載入的驅動是否和調用類使用的是同一個類載入器.要是不使用同一個載入器,他們會相互不可見,進而無法使用.

    private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {          boolean result = false;          if(driver != null) {              Class<?> aClass = null;              try {                  aClass =  Class.forName(driver.getClass().getName(), true, classLoader);//方法獲得類,該方法返回與給定字元串名的類或介面的Class對象,使用給定的類載入器進行載入,然後通過              } catch (Exception ex) {                  result = false;              }                 result = ( aClass == driver.getClass() ) ? true : false;//如果不是同一個載入器這個值不會相等.          }            return result;      }  

    整體的源碼:

     @CallerSensitive      public static Connection getConnection(String url)          throws SQLException {            java.util.Properties info = new java.util.Properties();//這個是讀取配置文件的類的實例          return (getConnection(url, info, Reflection.getCallerClass()));          //eflection.getCallerClass()可以得到調用者的類.這個方法是很好用的.      }        //  用於根據url、對應的屬性資訊在registeredDrivers中找到合適的註冊的驅動創建資料庫鏈接      private static Connection getConnection(          String url, java.util.Properties info, Class<?> caller) throws SQLException {          /*           * When callerCl is null, we should check the application's           * (which is invoking this class indirectly)           * classloader, so that the JDBC driver class outside rt.jar           * can be loaded from here.           */          //這個意思如果為空,就說明並沒有註冊驅動程式,需要檢查.          ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;          synchronized(DriverManager.class) {              // synchronize loading of the correct classloader.              if (callerCL == null) {                  callerCL = Thread.currentThread().getContextClassLoader();              }          }            if(url == null) {              throw new SQLException("The url cannot be null", "08001");          }            println("DriverManager.getConnection("" + url + "")");            // Walk through the loaded registeredDrivers attempting to make a connection.          // Remember the first exception that gets raised so we can reraise it.          SQLException reason = null;            for(DriverInfo aDriver : registeredDrivers) {              // If the caller does not have permission to load the driver then              // skip it.           //一個應用中有可能會有多個資料庫驅動,需要判斷資料庫連接的調用者(調用getConnection()方法的對象)是否與驅動相匹配              if(isDriverAllowed(aDriver.driver, callerCL)) {                  try {                      println("    trying " + aDriver.driver.getClass().getName());                      Connection con = aDriver.driver.connect(url, info);                      if (con != null) {                          // Success!                          println("getConnection returning " + aDriver.driver.getClass().getName());                          return (con);                      }                  } catch (SQLException ex) {                      if (reason == null) {                          reason = ex;                      }                  }                } else {                  println("    skipping: " + aDriver.getClass().getName());              }            }            // if we got here nobody could connect.          if (reason != null)    {              println("getConnection failed: " + reason);              throw reason;          }            println("getConnection: no suitable driver found for "+ url);          throw new SQLException("No suitable driver found for "+ url, "08001");      }  }    //一個應用中有可能會有多個資料庫驅動,需要判斷資料庫連接的調用者(調用getConnection()方法的對象)是否與驅動相匹配  private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {          boolean result = false;          if(driver != null) {              Class<?> aClass = null;              try {                  aClass =  Class.forName(driver.getClass().getName(), true, classLoader);              } catch (Exception ex) {                  result = false;              }                 result = ( aClass == driver.getClass() ) ? true : false;          }            return result;      }    

DriverManager的源碼

/**管理一個集合JDBC驅動的基礎服務  注意:在新的JDBC2.0api中實現了新的DataSource介面,提供了另一種鏈接數據源的方式。  使用DataSource的對象是首選方案  */  public class DriverManager {        // 註冊了JDBC驅動的集合,記不記得上面講的註冊過程.這個就是那個形成的東西      private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();          /**      通過檢查jdcb.properties載入初始化JDBC驅動       */      static {          loadInitialDrivers();          println("JDBC DriverManager initialized");      }    /*  *對外使用提供資料庫連接的方法,  *重點說明Reflection.getCallerClass()方法,該方法返回調用者的類  */      @CallerSensitive      public static Connection getConnection(String url)          throws SQLException {            java.util.Properties info = new java.util.Properties();          return (getConnection(url, info, Reflection.getCallerClass()));      }        //  用於根據url、對應的屬性資訊在registeredDrivers中找到合適的註冊的驅動創建資料庫鏈接      private static Connection getConnection(          String url, java.util.Properties info, Class<?> caller) throws SQLException {          /*           * When callerCl is null, we should check the application's           * (which is invoking this class indirectly)           * classloader, so that the JDBC driver class outside rt.jar           * can be loaded from here.           */          ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;          synchronized(DriverManager.class) {              // synchronize loading of the correct classloader.              if (callerCL == null) {                  callerCL = Thread.currentThread().getContextClassLoader();              }          }            if(url == null) {              throw new SQLException("The url cannot be null", "08001");          }            println("DriverManager.getConnection("" + url + "")");            // Walk through the loaded registeredDrivers attempting to make a connection.          // Remember the first exception that gets raised so we can reraise it.          SQLException reason = null;            for(DriverInfo aDriver : registeredDrivers) {              // If the caller does not have permission to load the driver then              // skip it.           //一個應用中有可能會有多個資料庫驅動,需要判斷資料庫連接的調用者(調用getConnection()方法的對象)是否與驅動相匹配              if(isDriverAllowed(aDriver.driver, callerCL)) {                  try {                      println("    trying " + aDriver.driver.getClass().getName());                      Connection con = aDriver.driver.connect(url, info);                      if (con != null) {                          // Success!                          println("getConnection returning " + aDriver.driver.getClass().getName());                          return (con);                      }                  } catch (SQLException ex) {                      if (reason == null) {                          reason = ex;                      }                  }                } else {                  println("    skipping: " + aDriver.getClass().getName());              }            }            // if we got here nobody could connect.          if (reason != null)    {              println("getConnection failed: " + reason);              throw reason;          }            println("getConnection: no suitable driver found for "+ url);          throw new SQLException("No suitable driver found for "+ url, "08001");      }  }      private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {          boolean result = false;          if(driver != null) {              Class<?> aClass = null;              try {                  aClass =  Class.forName(driver.getClass().getName(), true, classLoader);              } catch (Exception ex) {                  result = false;              }                 result = ( aClass == driver.getClass() ) ? true : false;          }            return result;      }    //根據URL從registeredDrivers 中獲得驅動,根據Reflection.getCallerClass()返回的調用者類,在registeredDrivers 中進行匹配  //API文檔:試圖查找能理解給定 URL 的驅動程式。DriverManager 試圖從已註冊的驅動程式集中選擇一個適當的驅動程式。    @CallerSensitive      public static Driver getDriver(String url)          throws SQLException {            println("DriverManager.getDriver("" + url + "")");            Class<?> callerClass = Reflection.getCallerClass();            // Walk through the loaded registeredDrivers attempting to locate someone          // who understands the given URL.          for (DriverInfo aDriver : registeredDrivers) {              // If the caller does not have permission to load the driver then              // skip it.              if(isDriverAllowed(aDriver.driver, callerClass)) {                  try {                      if(aDriver.driver.acceptsURL(url)) {                          // Success!                          println("getDriver returning " + aDriver.driver.getClass().getName());                      return (aDriver.driver);                      }                    } catch(SQLException sqe) {                      // Drop through and try the next driver.                  }              } else {                  println("    skipping: " + aDriver.driver.getClass().getName());              }            }            println("getDriver: no suitable driver");          throw new SQLException("No suitable driver", "08001");      }      /*  *註冊數據驅動,使用同步方式,最終保存在CopyOnWriteArrayList的集合中  */      public static synchronized void registerDriver(java.sql.Driver driver,              DriverAction da)          throws SQLException {            /* Register the driver if it has not already been added to our list */          if(driver != null) {              registeredDrivers.addIfAbsent(new DriverInfo(driver, da));          } else {              // This is for compatibility with the original DriverManager              throw new NullPointerException();          }            println("registerDriver: " + driver);        }  

connection是一個介面,這個由DriverManger產生的東西有著數量眾多的方法

Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.80.10:1521:orcl", "system","aA107824");  connection.SetAtuoCommit(true);//設置為自動提交狀態  System.out.println(connection.getAutoCommit());// 檢索此 Connection 對象的當前自動提交模式。  //true   Statement statement=connection.createStatement();//創建一個statement對象,之後會講  int count = statement.executeUpdate("insert into student values(5,'郭美美','女',58,'北京市海淀區')");  connection.commit();//手動提交程式碼  connection.rollback();//手動回滾更改  connection.close()://立刻關閉這個資源  connection.isclose();//true      

發送 操作資料庫的語句(createStatement)

這個部分就是到了創Statement的地方了

 try {  		  Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@192.168.80.10:1521:orcl","system","aA107824");  		  Statement statement=conn.createStatement();  	  }catch (SQLException e) {  		// TODO: handle exception  	e.printStackTrace();  	  }  

新手看到這裡就可以了

構建Statement的方法有很多種,這裡挑兩個主要講

  • createStatement()方法
  • PreparedStatement()方法
  • 這兩個方法最後返回的對象也是不同的

先來講createStatement()方法.

這個方法分為很多個參數,從無參到很多參數都有,我們找一個全的講.

Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,  					ResultSet.CONCUR_UPDATABLE);  

你可以發現這個方法裡面有兩個參數int resultSetTypeint resultSetConcurrency

  • resultSetType可填寫的內容如下

    • TYPE_FORWARD_ONLYResultSet指針只能安裝列順序向前移動,也就是說在取得name列之後,將不能再返回獲取id列的值
    • TYPE_SCROLL_INSENSITIVEResultSet指針可以前後移動,INSENSITIVE表示不及時更新,就是如果資料庫里的數據修改過,並不在ResultSet中反映出來;
    • TYPE_SCROLL_SENSITIVEResultSet指針可以前後移動,SENSITIVE表示及時跟蹤資料庫的更新,以便更改ResultSet中的數據。
  • int resultSetConcurrency:可填寫的內容如下

    • ResultSet.CONCUR_READ_ONLY

    • ResultSet.CONCUR_UPDATABLE


    當然講到這裡就要返回對象了 satement對象

    Statement 是 Java 執行資料庫操作的一個重要介面,用於在已經建立資料庫連接的基礎上,向資料庫發送要執行的SQL語句。Statement對象,用於執行不帶參數的簡單SQL語句。    

Statement子介面有:CallableStatement, PreparedStatement。

Statement 介面提供了執行語句和獲取結果的基本方法。PreparedStatement 介面添加了處理 IN 參數的方法;而 CallableStatement 添加了處理 OUT 參數的方法。

  這也是圖1-1和圖1-2的最後一個部分**執行並處理返回結果(executeQuery)**     `satement`對象的方法比較少,比較簡單.    最主要的就是下面得這個方法,其作用是用各種方式向資料庫發送SQL語句.    ```java  //executeUpdate方法,向資料庫傳遞增刪改的SQL語句  int count = statement.executeUpdate("insert into student values(20,'郭美美','女',58,'北京市海淀區')");  //返回從資料庫搜索的數據,用ResultSet格式存儲.  ResultSet resultSet=statement.executeQuery("select*from student");  //獲取結果集合的行數,該數是根據此 Statement 對象生成的 ResultSet 對象的默認獲取大小。  statement.getFetchSize();//1,因為只插入了一條數據  //獲取從資料庫表獲取行的方向,該方向是根據此 Statement 對象生成的結果集合的默認值。  statement.getFetchDirection()//1000,這個應該是一個常量,就是正向的意思      //關閉staement對象,釋放佔有的jdbc資源,而不是等連接關閉的時候   statement.close();  

在來講PreparedStatement()方法

PreparedStatement是一種預編譯的方法,可以有效地防止SQL注入的危險,所以在正常的情況下大部分都使用這個方法而不是createStatement()

這個方法不能一個個方法的講解,會很亂.所以看一下下面得程式碼.

其中PreparedStatement statement2 = connection.prepareStatement("update student set sname=? where sid=? ");方法是用來創建一個PreparedStatement對象的.在這裡面的問號就類似於參數.不填入數據,等著之後由程式設計師進行設置.

statement2.setString(1, "許佳琪");這句程式碼就是設置這個參數中的內容.第一個參數是?所在的位置.比如第一個?就填1,第二個?就填2.然後這個?所在位置的屬性也決定了使用什麼方法.比如在student表中sname是varchar2類型,那麼這個時候就要用setString()方法.如果是個SID呢?

當然就是用setInt方法了.

這個在下面的例子中可以看出來.

但是光是設定了這個sql語句是沒有效果的.

還要用excute()方法將這個語句發送到資料庫中去才有效果.

一個小栗子:

	PreparedStatement statement2 = connection.prepareStatement("update student set sname=? where sid=? ");// 有一個預編譯的過程.  			statement2.setString(1, "許佳琪");// 設置String的數據類型  			statement2.setInt(2, 4);// 設置int的數值類型,第一個參數是?所在的位置,比如sname=?是第一個?,sid=?是第二個問好.  //		   statement2.executeUpdate("insert into student values(3,'K律','女',57,'北京市')");//插入升級語句  			statement2.execute();// 似乎是必須有這一步,要不然發送不上去  			System.out.println("是否是自動提交模式" + connection.getAutoCommit());// getAutoCommit()用來判斷是否是用來提交的              connection.commit();  

兩個方法有什麼不同?

其實主要是因為有一個預編譯的過程

PreparedStatement和createStatement的不同.


以上就是JDBC的詳解內容。相信你看了這個內容,就能對JDBC有一個比較深入的了解。