JDBC是一個Java API,用中文能夠通俗的解釋爲,使用Java語言訪問訪問數據庫的一套接口集合。這是調用者(程序員)和實行者(數據庫廠商)之間的協議,能夠訪問任何類型表列數據,特別是存儲在關係數據庫中的數據。JDBC(java database connection)html
既然JDBC也是由Java類和接口組成,那麼首先要學習的是,它屬於哪一個包下面。
在JDBC中包含了兩個包:java.sql和javax.sqljava
能夠看出JDBC在圖中的位置,前文說過是程序員與數據庫廠商之間的協議。首先Java提拱了JDBC的接口,服務器廠商提供了JDBC的驅動,這樣咱們經過JDBC Driver Manager來進行管理數據庫。mysql
DriverManager: 這個類管理數據庫驅動程序的列表。 肯定內容是否符合從Java應用程序使用的通訊子協議正確的數據庫驅動程序的鏈接請求。 識別JDBC在必定子協議的第一個驅動器將被用來創建數據庫鏈接。 Driver: 此接口處理與數據庫服務器通訊。 不多直接直接使用驅動程序(Driver)對象,通常使用DriverManager中的對象, 它用於管理此類型的對象。它也抽象與驅動程序對象工做相關的詳細信息 Connection : 此接口與接觸數據庫的全部方法。 鏈接對象表示通訊上下文,即,與數據庫中的全部的通訊是經過此惟一的鏈接對象。 Statement : 可使用這個接口建立的對象的SQL語句提交到數據庫。 一些派生的接口接受除執行存儲過程的參數。 ResultSet: 這些對象保存從數據庫後,執行使用Statement對象的SQL查詢中檢索數據。 它做爲一個迭代器,能夠經過移動它來檢索下一個數據。 SQLException: 這個類用於處理髮生在數據庫應用程序中的任何錯誤。
①Class.forName("com.mysql.jdbc.Driver");
Java規範中明確規定,全部的驅動程序必須在靜態初始代碼塊中將驅動註冊到驅動程序的管理器中,程序員
static{ try{ Class.forName(driver); } catch(Exception ex){ ex.printStackTrace(); } }
這樣作的好處是,再類被加載到工程時就被執行了,並且之執行一次,數據庫驅動只要加載一次就能夠了。sql
【知識點】 Class類
在這裏面咱們看到了,這個裏面有一個Class類,它調用了一個forName()方法,那麼這個Class類是個什麼東西呢?
Class類是在java.lang包下的,因此不用手動的導入。
看一下Class的構造方法[1]數據庫
private Class(ClassLoader loader){ classLoader = loader; }
不用去管什麼ClassLoader,看了一眼private關鍵字,應該就知道了,當private修飾構造方法的時候,說明該類是不能在類的外面進行實例化的。因此Class類不能像普通的類同樣,以new Xxx()
的形式進行建立對象,它的對象只能由JVM建立。[2]編程
Class類究竟是什麼呢?不妨咱們通俗的說一下,Java程序在運行的時候,咱們會讓它建立一些對象,系統經過RTTI對全部的對象進行運行時類型表示。bootstrap
【知識點】RTTI
RTTI(runtime type Identification),經過運行時類型信息程序可以使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。
咱們把它叫成運行時類型信息,或許更加的好理解。這個是Java語言中很強大的機制。
首先要知道的運行時都會存在哪些類型信息呢?若是一個類繼承自另外一個類,在建立子類的對象時,須要RTTI存儲這些關係,他會有typeid操做符,返回指針和引用所指的實際類型,typeid函數等等,咱們簡要的理解爲Java的RTTI裏面就是記錄着各類類型的信息。
如下是一些經常使用的方式。緩存
咱們能夠針對於基類來編程,從而下降程序的耦合度,以Java來講經常經過繼承的方式,來達到這種效果。服務器
public class Demo { public static void main(String[] args) { Animal [] animals = new Animal[2]; animals[0] = new Tiger(); animals[1] = new fish(); for (Animal animal : animals) { animal.breath(); } } } abstract class Animal { abstract void breath(); } class Tiger extends Animal{ @Override void breath() { // TODO Auto-generated method stub } } class fish extends Animal{ @Override void breath() { // TODO Auto-generated method stub } }
像這種繼承關係,之因此可以編譯經過,是由於Tiger和FIsh都會向上轉爲基類,他們自身的類型信息會丟失,可是程序運行的時候,當咱們調用animal.breath();
它們卻能準確的找到所屬類型的方法進行調用,這是爲何呢?這就是運行時綁定(動態綁定)機制。
進一步分析,RTTI裏面就是存儲着程序運行時類型的方法列表,繼承結構等等信息。
java xxx.class
,這個時候類纔開始加載到虛擬機,通常來講一個class只會被加載一次,下一次就會從Jvm的class緩存中獲取,不會再去文件系統中獲取了。具體的過程是:java這個命令是java.exe進行的,java.exe找到jre,再找到JRE中的jvm.dll,這個就是Java 虛擬機,這個時候虛擬機啓動,它首先就加載了第一個類加載器--Bootstrap Loader,這個BootstrapLoader又加載了第二個類加載器ExtClassLoader,設定parent爲null(本質上是bootstraploader,可是它是由C++編寫的,沒法找到這個實例)這個BootstrapLoader又加載了最後一個類加載器APPClassLoader,設定它的parent爲ExtClassLoader。Class類原理:當各種被實例化後,JVM會自動建立該類的Class對象,或者經過類加載器defineClass()方法生成。
全部的類都繼承自Object
類,Object類有一個getClass()
方法,這個方法能夠獲取某個對象的Class引用,這個引用就是指向的是Class類的對象。
由於是針對類的關係而言,因此一個Class對象對應多個類的實例化。
獲取Class對象:
經過類名來獲取:
public class Hello{} Class hello = Class.forName("Hello");
經過對象來獲取。
public class Hello{} Hello h = new Hello(); Class hello = h.getClass();
經過類字面量來獲取
public class Hello{} Class hello = Hello.class;
【注】使用第三種方法來獲取Class對象,Jvm不會加載類,也就不會初始化,而其餘兩種方法,會自動加載並初始化類。
回到正題。第二種註冊數據庫驅動的方法是。
②
Driver drv = new oracle.jdbc.driver.OracleDriver(); DriverManager.registerDriver(drv);
③ 編譯時在虛擬機中加載驅動
java -D jdbc.drivers = 驅動全名 類名 例如: javac -D jdbc.drivers = oracle.jdbc.driver.OracleDrvier xxx.java
【問題】如下是知乎的問題
JDBC註冊數據庫驅動,啥意思?
Class.forName("com.mysql.jdbc.Driver")不是反射麼,獲得這個類的信息,和註冊數據庫驅動有啥關係?
答:
做者:木女孩
連接:https://www.zhihu.com/questio...
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
建立一個Connection
對象,創建物理鏈接
static final String USER = "XXX"; static final String PASSWORD = "xxx"; System.out.println("database is connecting"); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.23:1521:tarena",USER,PASSWORD);
回想以前的結構圖,咱們能夠知道,經過DriverManager
能夠操做數據庫的驅動,從而進行數據庫的相關操做。
這裏Connection
鏈接就是經過DriverManager
的靜態方法getCOnnection()
來獲得的,這個方法的實質是把參數傳到實際的Driver
中的connect()
方法來忽的數據庫的鏈接的。
下面是一些格式的補充:
Oracle URL的格式:jdbc:oracle:thin:(協議)@XXX.XXX.X.XXX:XXXX(IP地址及端口號):XXXXXX(所使用的庫名)
MySql URL:jdbc:mysql://192.168.8.21:3306/test
SQLServer URL 的寫法 jdbc:microsoft:sqlserver://192.168.8.21:1433
經過Connection
對象createStatement()
來建立Statement對象
Statement stm = conn.createStatement();
經過Statement來執行
stm.excuteQuery(Sring sql); //返回一個查詢結果集 stm.excuteUpdate(String sql); //返回值爲 int 型,表示影響記錄的條數。 stm.excute(String sql);//返回 true,表示查詢;返回 false,表示其它操做。
經過excuteQuery(String sql)
可使用select語句進行查詢,而且返回一個結果集ResultSet。ResultSet的next()方法會操做一個遊標從第一條記錄的前面開始讀取,直到最後一條記錄。
【注】只有執行select語句纔有結果集返回。
while(rs.next()){ System.out.println(rs.getInt("id)); System.out.println(rs.getString("name")); }
rs.close(); stm.close(); conn.close()
應該順序關閉,若是先關閉Connetction後面可能還須要其餘的Statement鏈接。
[1] 淺談Java中的Class類
[2] Java中Class類及用法
[3] RTTI
[4] 深刻Java類型信息:RTTI
[5] 類加載的全過程
[6] java類加載過程
[7] 深刻理解java類加載起ClassLoader