摘要:同時(shí)也有一些兒高級(jí)的處理,比如批處理更新事務(wù)隔離和可滾動(dòng)結(jié)果集等。連接對(duì)象表示通信上下文,即,與數(shù)據(jù)庫(kù)中的所有的通信是通過(guò)此唯一的連接對(duì)象。因?yàn)槭轻槍?duì)類的關(guān)系而言,所以一個(gè)對(duì)象對(duì)應(yīng)多個(gè)類的實(shí)例化。返回表示查詢返回表示其它操作。
JDBC是什么?
JDBC是一個(gè)Java API,用中文可以通俗的解釋為,使用Java語(yǔ)言訪問(wèn)訪問(wèn)數(shù)據(jù)庫(kù)的一套接口集合。這是調(diào)用者(程序員)和實(shí)行者(數(shù)據(jù)庫(kù)廠商)之間的協(xié)議,可以訪問(wèn)任何類型表列數(shù)據(jù),特別是存儲(chǔ)在關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)。JDBC(java database connection)
既然JDBC也是由Java類和接口組成,那么首先要學(xué)習(xí)的是,它屬于哪個(gè)包下面。
在JDBC中包含了兩個(gè)包:java.sql和javax.sql
java.sql:基本功能,這個(gè)包中的類和接口主要針對(duì)基本的數(shù)據(jù)庫(kù)編程服務(wù),如生成連接、執(zhí)行語(yǔ)句以及準(zhǔn)備語(yǔ)句和運(yùn)行批處理查詢等。同時(shí)也有一些兒高級(jí)的處理,比如批處理更新、事務(wù)隔離和可滾動(dòng)結(jié)果集等。
javax.sql:擴(kuò)展功能。它主要為數(shù)據(jù)庫(kù)方面的高級(jí)操作提供了接口和類。如為連接管理、分布式事務(wù)和舊有的連接提供了更好的抽象,它引入了容器管理的連接池、分布式事務(wù)和行集等。
JDBC結(jié)構(gòu)概述可以看出JDBC在圖中的位置,前文說(shuō)過(guò)是程序員與數(shù)據(jù)庫(kù)廠商之間的協(xié)議。首先Java提拱了JDBC的接口,服務(wù)器廠商提供了JDBC的驅(qū)動(dòng),這樣我們通過(guò)JDBC Driver Manager來(lái)進(jìn)行管理數(shù)據(jù)庫(kù)。
主要接口和類DriverManager: 這個(gè)類管理數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序的列表。 確定內(nèi)容是否符合從Java應(yīng)用程序使用的通信子協(xié)議正確的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序的連接請(qǐng)求。 識(shí)別JDBC在一定子協(xié)議的第一個(gè)驅(qū)動(dòng)器將被用來(lái)建立數(shù)據(jù)庫(kù)連接。 Driver: 此接口處理與數(shù)據(jù)庫(kù)服務(wù)器通信。 很少直接直接使用驅(qū)動(dòng)程序(Driver)對(duì)象,一般使用DriverManager中的對(duì)象, 它用于管理此類型的對(duì)象。它也抽象與驅(qū)動(dòng)程序?qū)ο蠊ぷ飨嚓P(guān)的詳細(xì)信息 Connection : 此接口與接觸數(shù)據(jù)庫(kù)的所有方法。 連接對(duì)象表示通信上下文,即,與數(shù)據(jù)庫(kù)中的所有的通信是通過(guò)此唯一的連接對(duì)象。 Statement : 可以使用這個(gè)接口創(chuàng)建的對(duì)象的SQL語(yǔ)句提交到數(shù)據(jù)庫(kù)。 一些派生的接口接受除執(zhí)行存儲(chǔ)過(guò)程的參數(shù)。 ResultSet: 這些對(duì)象保存從數(shù)據(jù)庫(kù)后,執(zhí)行使用Statement對(duì)象的SQL查詢中檢索數(shù)據(jù)。 它作為一個(gè)迭代器,可以通過(guò)移動(dòng)它來(lái)檢索下一個(gè)數(shù)據(jù)。 SQLException: 這個(gè)類用于處理發(fā)生在數(shù)據(jù)庫(kù)應(yīng)用程序中的任何錯(cuò)誤。JDBC編程(以mysql為例) 注冊(cè)驅(qū)動(dòng)(有三種方式)
①Class.forName("com.mysql.jdbc.Driver"); Java規(guī)范中明確規(guī)定,所有的驅(qū)動(dòng)程序必須在靜態(tài)初始代碼塊中將驅(qū)動(dòng)注冊(cè)到驅(qū)動(dòng)程序的管理器中,
static{ try{ Class.forName(driver); } catch(Exception ex){ ex.printStackTrace(); } }
這樣做的好處是,再類被加載到工程時(shí)就被執(zhí)行了,而且之執(zhí)行一次,數(shù)據(jù)庫(kù)驅(qū)動(dòng)只要加載一次就可以了。
【知識(shí)點(diǎn)】 Class類
在這里面我們看到了,這個(gè)里面有一個(gè)Class類,它調(diào)用了一個(gè)forName()方法,那么這個(gè)Class類是個(gè)什么東西呢?
Class類是在java.lang包下的,所以不用手動(dòng)的導(dǎo)入。
看一下Class的構(gòu)造方法[1]
private Class(ClassLoader loader){ classLoader = loader; }
不用去管什么ClassLoader,看了一眼private關(guān)鍵字,應(yīng)該就知道了,當(dāng)private修飾構(gòu)造方法的時(shí)候,說(shuō)明該類是不能在類的外面進(jìn)行實(shí)例化的。所以Class類不能像普通的類一樣,以new Xxx()的形式進(jìn)行創(chuàng)建對(duì)象,它的對(duì)象只能由JVM創(chuàng)建。[2]
Class類到底是什么呢?不妨我們通俗的說(shuō)一下,Java程序在運(yùn)行的時(shí)候,我們會(huì)讓它創(chuàng)建一些對(duì)象,系統(tǒng)通過(guò)RTTI對(duì)所有的對(duì)象進(jìn)行運(yùn)行時(shí)類型表示。
【知識(shí)點(diǎn)】RTTI
RTTI(runtime type Identification),通過(guò)運(yùn)行時(shí)類型信息程序能夠使用基類的指針或引用來(lái)檢查這些指針或引用所指的對(duì)象的實(shí)際派生類型。
我們把它叫成運(yùn)行時(shí)類型信息,或許更加的好理解。這個(gè)是Java語(yǔ)言中很強(qiáng)大的機(jī)制。
首先要知道的運(yùn)行時(shí)都會(huì)存在哪些類型信息呢?如果一個(gè)類繼承自另一個(gè)類,在創(chuàng)建子類的對(duì)象時(shí),需要RTTI存儲(chǔ)這些關(guān)系,他會(huì)有typeid操作符,返回指針和引用所指的實(shí)際類型,typeid函數(shù)等等,我們簡(jiǎn)要的理解為Java的RTTI里面就是記錄著各種類型的信息。
以下是一些常用的方式。
A = (A)b;向下轉(zhuǎn)型
我們可以針對(duì)于基類來(lái)編程,從而降低程序的耦合度,以Java來(lái)說(shuō)常常通過(guò)繼承的方式,來(lái)達(dá)到這種效果。
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 } }
像這種繼承關(guān)系,之所以能夠編譯通過(guò),是因?yàn)門(mén)iger和FIsh都會(huì)向上轉(zhuǎn)為基類,他們自身的類型信息會(huì)丟失,但是程序運(yùn)行的時(shí)候,當(dāng)我們調(diào)用animal.breath();它們卻能準(zhǔn)確的找到所屬類型的方法進(jìn)行調(diào)用,這是為什么呢?這就是運(yùn)行時(shí)綁定(動(dòng)態(tài)綁定)機(jī)制。
進(jìn)一步分析,RTTI里面就是存儲(chǔ)著程序運(yùn)行時(shí)類型的方法列表,繼承結(jié)構(gòu)等等信息。
load class(類的裝載過(guò)程)
類從被加載到卸載,他的生命周期包括:加載 驗(yàn)證 準(zhǔn)備 解析 初始化 使用 和卸載七個(gè)階段
而類的加載階段有:加載 驗(yàn)證 準(zhǔn)備 解析 初始化。
重點(diǎn)說(shuō)一下加載階段:類只有在要運(yùn)行的時(shí)候才會(huì)被加載進(jìn)JVM,編譯后的class文件現(xiàn)在還沒(méi)有加載到j(luò)vm,當(dāng)我們命令行輸入java xxx.class,這個(gè)時(shí)候類才開(kāi)始加載到虛擬機(jī),一般來(lái)說(shuō)一個(gè)class只會(huì)被加載一次,下一次就會(huì)從Jvm的class緩存中獲取,不會(huì)再去文件系統(tǒng)中獲取了。具體的過(guò)程是:java這個(gè)命令是java.exe進(jìn)行的,java.exe找到j(luò)re,再找到JRE中的jvm.dll,這個(gè)就是Java 虛擬機(jī),這個(gè)時(shí)候虛擬機(jī)啟動(dòng),它首先就加載了第一個(gè)類加載器--Bootstrap Loader,這個(gè)BootstrapLoader又加載了第二個(gè)類加載器ExtClassLoader,設(shè)定parent為null(本質(zhì)上是bootstraploader,但是它是由C++編寫(xiě)的,無(wú)法找到這個(gè)實(shí)例)這個(gè)BootstrapLoader又加載了最后一個(gè)類加載器APPClassLoader,設(shè)定它的parent為ExtClassLoader。
類的類class of classes
Class類原理:當(dāng)各類被實(shí)例化后,JVM會(huì)自動(dòng)創(chuàng)建該類的Class對(duì)象,或者通過(guò)類加載器defineClass()方法生成。
所有的類都繼承自Object類,Object類有一個(gè)getClass()方法,這個(gè)方法可以獲取某個(gè)對(duì)象的Class引用,這個(gè)引用就是指向的是Class類的對(duì)象。
因?yàn)槭轻槍?duì)類的關(guān)系而言,所以一個(gè)Class對(duì)象對(duì)應(yīng)多個(gè)類的實(shí)例化。
獲取Class對(duì)象:
通過(guò)類名來(lái)獲?。?/p>
public class Hello{} Class hello = Class.forName("Hello");
通過(guò)對(duì)象來(lái)獲取。
public class Hello{} Hello h = new Hello(); Class hello = h.getClass();
通過(guò)類字面量來(lái)獲取
public class Hello{} Class hello = Hello.class;
【注】使用第三種方法來(lái)獲取Class對(duì)象,Jvm不會(huì)加載類,也就不會(huì)初始化,而其他兩種方法,會(huì)自動(dòng)加載并初始化類。
回到正題。第二種注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的方法是。
②
Driver drv = new oracle.jdbc.driver.OracleDriver(); DriverManager.registerDriver(drv);
③ 編譯時(shí)在虛擬機(jī)中加載驅(qū)動(dòng)
java -D jdbc.drivers = 驅(qū)動(dòng)全名 類名 例如: javac -D jdbc.drivers = oracle.jdbc.driver.OracleDrvier xxx.java
【問(wèn)題】以下是知乎的問(wèn)題
JDBC注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng),啥意思?
Class.forName("com.mysql.jdbc.Driver")不是反射么,得到這個(gè)類的信息,和注冊(cè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)有啥關(guān)系?
答:
作者:木女孩
鏈接:https://www.zhihu.com/questio...
來(lái)源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
創(chuàng)建一個(gè)Connection對(duì)象,建立物理連接
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);
回想之前的結(jié)構(gòu)圖,我們可以知道,通過(guò)DriverManager可以操作數(shù)據(jù)庫(kù)的驅(qū)動(dòng),從而進(jìn)行數(shù)據(jù)庫(kù)的相關(guān)操作。
這里Connection連接就是通過(guò)DriverManager的靜態(tài)方法getCOnnection()來(lái)得到的,這個(gè)方法的實(shí)質(zhì)是把參數(shù)傳到實(shí)際的Driver中的connect()方法來(lái)忽的數(shù)據(jù)庫(kù)的連接的。
下面是一些格式的補(bǔ)充:
Oracle URL的格式:jdbc:oracle:thin:(協(xié)議)@XXX.XXX.X.XXX:XXXX(IP地址及端口號(hào)):XXXXXX(所使用的庫(kù)名)
MySql URL:jdbc:mysql://192.168.8.21:3306/test
SQLServer URL 的寫(xiě)法 jdbc:microsoft:sqlserver://192.168.8.21:1433
通過(guò)Connection對(duì)象createStatement()來(lái)創(chuàng)建Statement對(duì)象
Statement stm = conn.createStatement();執(zhí)行SQL語(yǔ)句
通過(guò)Statement來(lái)執(zhí)行
stm.excuteQuery(Sring sql); //返回一個(gè)查詢結(jié)果集 stm.excuteUpdate(String sql); //返回值為 int 型,表示影響記錄的條數(shù)。 stm.excute(String sql);//返回 true,表示查詢;返回 false,表示其它操作。處理結(jié)果集ResultSet
通過(guò)excuteQuery(String sql)可以使用select語(yǔ)句進(jìn)行查詢,并且返回一個(gè)結(jié)果集ResultSet。ResultSet的next()方法會(huì)操作一個(gè)游標(biāo)從第一條記錄的前面開(kāi)始讀取,直到最后一條記錄。
【注】只有執(zhí)行select語(yǔ)句才有結(jié)果集返回。
while(rs.next()){ System.out.println(rs.getInt("id)); System.out.println(rs.getString("name")); }關(guān)閉數(shù)據(jù)庫(kù)連接(釋放資源)
rs.close(); stm.close(); conn.close()
應(yīng)該順序關(guān)閉,如果先關(guān)閉Connetction后面可能還需要其他的Statement連接。
參考資料[1] 淺談Java中的Class類
[2] Java中Class類及用法
[3] RTTI
[4] 深入Java類型信息:RTTI
[5] 類加載的全過(guò)程
[6] java類加載過(guò)程
[7] 深入理解java類加載起ClassLoader
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68817.html
摘要:寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開(kāi)發(fā)工具,比如或者來(lái)學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
摘要:寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開(kāi)發(fā)工具,比如或者來(lái)學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
摘要:寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。這個(gè)階段學(xué)習(xí)的時(shí)候,要學(xué)會(huì)使用開(kāi)發(fā)工具,比如或者來(lái)學(xué)習(xí)。這個(gè)階段需要自己對(duì)自己有很強(qiáng)的自律去學(xué)習(xí),不要看了一半就放棄了。 showImg(https://segmentfault.com/img/bVbaNtw?w=1232&h=822); 寫(xiě)這篇總結(jié),主要是記錄下自己的學(xué)習(xí)經(jīng)歷,算是自己對(duì)知識(shí)的一個(gè)回顧。也給想要學(xué)習(xí) ...
閱讀 3090·2023-04-26 00:40
閱讀 2435·2021-09-27 13:47
閱讀 4353·2021-09-07 10:22
閱讀 2990·2021-09-06 15:02
閱讀 3348·2021-09-04 16:45
閱讀 2534·2021-08-11 10:23
閱讀 3629·2021-07-26 23:38
閱讀 2923·2019-08-30 15:54