說了這么多年的JDBC抄沮,你了解它么跋核?

JDBC主要功能及職責

官方文檔對JDBC的解釋:Java數(shù)據(jù)庫連接 (JDBC,Java Database Connectivity) 合是,是針對Java編程語言與各種數(shù)據(jù)庫了罪、SQL數(shù)據(jù)庫和其他表格數(shù)據(jù)源(如電子表格或平面文件)之間獨立于數(shù)據(jù)庫的連接的行業(yè)標準。其中聪全,JDBC API 是基于 SQL 的數(shù)據(jù)庫訪問提供調用級 API泊藕。

JDBC是Java語言中提供的訪問關系型數(shù)據(jù)庫的接口。

JDBC的對數(shù)據(jù)源的操作基本如下圖:


1631243487(1).png

建立數(shù)據(jù)源連接(Connection)

  1. DataSource (官方推薦方式):調用JDBC 2.0提供的DataSource的getConnection()方法后,DataSource實例會返回一個與數(shù)據(jù)源建立連接的Connection對象娃圆。

    UnpooledDataSource dataSource = new UnpooledDataSource(driverClassLoader, "com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1/test", "root", "123");
    Connection connection = dataSource.getConnection();
    

    JDBC API中只提供了DataSource接口玫锋,沒有DataSource的具體實現(xiàn)。DataSource具體的實現(xiàn)由JDBC驅動程序提供讼呢,如JDBCDataSource撩鹿,MysqlDataSource等。目前主流的數(shù)據(jù)庫連接池(例如DBCP悦屏、C3P0节沦、Druid等)也都實現(xiàn)了DataSource接口

  2. DriverManager: JDBC 1.0使用DriverManager類生成一個與數(shù)據(jù)源連接的Connection對象,通過重載的getConnection()方法础爬,用來獲取Connection對象甫贯。當應用程序第一次通過URL連接數(shù)據(jù)源時,DriverManager會自動加載CLASSPATH下所有的JDBC驅動看蚜。

    Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:association_nested", "SA", "");
    

    DriverManager類會嘗試加載“jdbc.drivers”系統(tǒng)屬性中引用的驅動程序類叫搁。

執(zhí)行sql語句

數(shù)據(jù)源Connection建立后,通過Connection接口提供的方法來創(chuàng)建Statement供炎、PreparedStatement或者CallableStatement對象渴逻,就可以對數(shù)據(jù)源進行查詢和修改操作。

 Connection realConn = conn.getRealConnection();
 Statement statement = realConn.createStatement());
 statement.executeQuery("select * from t");

Statement接口實際是JDBC API中提供的SQL語句的執(zhí)行器音诫,Statement接口定義了executeQuery()查詢操作惨奕、executeUpdate()更新操作、executeBatch()批量操作纽竣、execute()查詢/更新操作墓贿、getResultSet()查詢結果集、getUpdateCount()更新操作影響的行數(shù)等等執(zhí)行和返回方法蜓氨。

a. 如果數(shù)據(jù)庫返回的更新數(shù)量大于Integer.MAX_VALUE聋袋,則需要調用executeLargeXXX()方法

b.int executeXXX(String sql, int autoGeneratedKeys)等方法,第二個參數(shù)(autoGeneratedKeys)可以為int穴吹,int[]幽勒,String[]等類型,通過autoGeneratedKeys/columnIndexes/columnNames參數(shù)告訴驅動程序哪些列是自動生成的鍵可以用于檢索港令。如果SQL語句不是INSERT語句啥容,columnNames參數(shù)就會被忽略。

處理SQL執(zhí)行結果

通過Statement接口執(zhí)行了sql語句顷霹,根據(jù)返回的ResultSet獲取sql執(zhí)行后的結果咪惠,遍歷獲取最終的查詢結果。ResultSet提供相關的getString(int columnIndex)淋淀,getBoolean(int columnIndex)等各種方法遥昧,根據(jù)JDBCType等各種枚舉最終將每列查詢結果的數(shù)據(jù)類型轉換為Java對應的類型。

關閉連接

當所有Sql語句執(zhí)行完成,并獲取結果集后炭臭,通過對應的close()方法永脓,正常關閉Statement和Connection。

JDBC 主要內容

Wrapper

Wrapper接口為使用JDBC的應用程序提供訪問原始類型的功能鞋仍,從而使用JDBC驅動中一些非標準的特性常摧。
Connection,DataSource威创,Statement落午,ResultSet,DatabaseMetaData等基礎接口繼承Wrapper肚豺,Wrapper包含unwrap()和isWrapperFor()兩個方法:

  • unwrap()方法用于返回未經過包裝的JDBC驅動原始類型實例板甘,可以通過該實例調用JDBC驅動中提供的非標準的方法。
  • isWrapperFor()方法用于判斷當前實例是否是JDBC驅動中某一類型的包裝類型详炬。

DataSource

DataSource優(yōu)點:

  1. 可以通過JNDI注冊數(shù)據(jù)源對象,然后在程序中用一個邏輯名稱來引用寞奸,JNDI會自動根據(jù)這個名稱找到與這個名稱綁定的DataSource對象呛谜。這樣就可以使用這個DataSource對象來建立和具體數(shù)據(jù)庫的連接。
  2. DataSource接口支持連接池和分布式事務上枪萄。連接池通過對連接的復用隐岛,不需要每次操作數(shù)據(jù)源時都新建一個物理連接,可以顯著地提高程序的效率瓷翻。

PooledConnection

當應用程序調用方法DataSource.getConnection時聚凹,返回一個Connection對象。但是當使用數(shù)據(jù)庫連接池時(例如Druid)齐帚,Connection對象實際上是到PooledConnection對象的句柄妒牙,是一個物理連接。

PooledConnection提供了連接池管理的句柄对妄。PooledConnection對象表示到數(shù)據(jù)源的物理連接湘今。當應用程序完成連接時,連接可以被回收而不是關閉剪菱,從而減少了需要建立的連接數(shù)摩瞎。開發(fā)人員一般不直接使用PooledConnection接口,它由管理連接池的中間層基礎設施使用孝常,即通過一個管理連接池的中間層基礎設施使用旗们。

  1. 建立連接

連接池管理器(通常是應用程序服務器)維護一個 PooledConnection的對象池。如果池中有可用的 PooledConnection 對象构灸,則連接池管理器返回一個Connection對象上渴,該對象是該物理連接的句柄。如果沒有PooledConnection對象可用,連接池管理器調用ConnectionPoolDataSource的(PooledConnection對象工廠)getPoolConnection方法來創(chuàng)建新的物理連接驰贷。一般對應實現(xiàn) ConnectionPoolDataSource 的 JDBC 驅動程序盛嘿,創(chuàng)建一個新的 PooledConnection 對象并返回一個句柄給它。如MysqlConnectionPoolDataSource實現(xiàn)如下:

public synchronized PooledConnection getPooledConnection() throws SQLException {
        try {
            Connection connection = this.getConnection();
            MysqlPooledConnection mysqlPooledConnection = MysqlPooledConnection.getInstance((JdbcConnection)connection);
            return mysqlPooledConnection;
        } catch (CJException var4) {
            throw SQLExceptionsMapping.translateException(var4);
        }
    }
  1. 關閉連接

當應用程序關閉連接時括袒,調用Connection的close方法次兆。當連接池完成時,連接池管理器會收到通知(使用ConnectionPool的addConnectionEventListener方法锹锰,將自己注冊為ConnectionEventListener對象)芥炭。連接池管理器停用PooledConnection對象的句柄并將PooledConnection對象返回到連接池,以便它可以再次使用恃慧。因此园蝠,當應用程序關閉其連接時,底層物理連接將被回收而不是被關閉痢士。 在連接池管理器調用PooledConnection的close方法之前彪薛,物理連接不會關閉。通常調用close方法來有序關閉服務器怠蹂。

調用Connection對象的commit()方法能夠關閉當前事務中創(chuàng)建的ResultSet對象善延。

  1. 分布式連接
  • XAConnection繼承PooledConnection,為分布式事務提供支持的對象城侧。XAConnection 對象可以通過XAResource對象加入分布式事務易遣。事務管理器,通常是中間層服務器的一部分嫌佑,通過XAResource對象管理XAConnection豆茫。應用不直接使用這個接口;它由在中間層服務器中工作的事務管理器使用屋摇。
  • XAConnection接口繼承了PooledConnection接口揩魂,具有所有PooledConnection的特性,我們可以調用XAConnection實例的getConnection()方法獲取java.sql.Connection對象

RowSet 和 ResultSet

  1. RowSet接口繼承java.sql包下的ResultSet接口炮温,提供了一組 JavaBeans 屬性肤京,允許將RowSet實例配置為連接到 JDBC 數(shù)據(jù)源并從數(shù)據(jù)源讀取一些數(shù)據(jù)(RowSet用于為數(shù)據(jù)源和應用程序在內容中建立一個映射)。一組 setter 方法(setInt茅特、setBytes忘分、setString等)提供了一種將輸入參數(shù)傳遞給行集的命令屬性的方法。此命令是行集在從關系數(shù)據(jù)庫獲取數(shù)據(jù)時使用的 SQL 查詢白修。RowSet接口支持 JavaBeans 事件妒峦,允許在行集上發(fā)生事件時通知應用程序中的其他組件,例如其值的更改兵睛。
  • RowSet對象可以建立一個與數(shù)據(jù)源的連接并在其整個生命周期中維持該連接肯骇,在這種情況下窥浪,該對象被稱為連接的RowSet

  • RowSet對象還可以建立一個與數(shù)據(jù)源的連接,從其獲取數(shù)據(jù)笛丙,然后關閉它漾脂,這種RowSet被稱為非連接RowSet。非連接Rowset可以在斷開時更改其數(shù)據(jù)胚鸯,然后將這些更改寫回底層數(shù)據(jù)源骨稿,不過它必須重新建立連接才能完成此操作。

相較于java.sql.ResultSet姜钳,RowSet的離線操作能夠有效地利用計算機內存減輕數(shù)據(jù)庫的負擔坦冠。由于數(shù)據(jù)操作都是在內存中進行,然后批量提交到數(shù)據(jù)源哥桥,因此靈活性和性能有很大的提高辙浑。RowSet默認是一個可滾動、可更新拟糕、可序列化的結果集判呕,而且它作為一個JavaBean組件,可以方便地在網絡間傳輸送滞,用于兩端的數(shù)據(jù)同步佛玄。通俗來講,RowSet就相當于數(shù)據(jù)庫表數(shù)據(jù)在應用程序內存中的映射累澡,我們所有的操作都可以直接與RowSet對象交互。RowSet與數(shù)據(jù)庫之間的數(shù)據(jù)同步般贼,開發(fā)人員不需要關心愧哟。

  1. ResultSet的類型、并行性和可保持性等屬性可以在調用Connection對象的createStatement()哼蛆、prepareStatement()或prepareCall()方法創(chuàng)建Statement對象時設置蕊梧,例如:
Connection connection = DriverManager.getConnection("abc");
Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT);

ResultSet類型

TYPE_FORWARD_ONLY(默認):游標只能向前移動,從第一行到最后一行

TYPE_SCROLL_INSENSITIVE:游標可以向前/向后滾動(相對于當前位置)腮介,也可以滾動到相對位置肥矢,ResultSet對象的修改不會影響對應的數(shù)據(jù)庫中的記錄

TYPE_SCROLL_SENSITIVE:游標可以向前/向后移動(相對于當前位置),也可以移動到絕對位置叠洗。ResultSet對象的修改會直接影響數(shù)據(jù)庫中的記錄

ResultSet并行性

CONCUR_READ_ONLY(默認):為ResultSet對象設置這種屬性后甘改,只能從ResulSet對象中讀取數(shù)據(jù),但是不能更新ResultSet對象中的數(shù)據(jù)灭抑。

CONCUR_UPDATABLE:該屬性表明十艾,既可以從ResulSet對象中讀取數(shù)據(jù),又能更新ResultSet中的數(shù)據(jù)腾节。

ResultSet可保持性

HOLD_CURSORS_OVER_COMMIT:當調用Connection對象的commit()方法時忘嫉,不關閉當前事務創(chuàng)建的ResultSet對象荤牍。

CLOSE_CURSORS_AT_COMMIT:當前事務創(chuàng)建的ResultSet對象在事務提交后會被關閉,這樣能夠提升系統(tǒng)性能庆冕。

ResultSet對象關閉后康吵,不會關閉由ResultSet對象創(chuàng)建的Blob、Clob访递、NClob或SQLXML對象晦嵌,除非調用這些對象的free()方法進行清除

事務

Connection接口中提供了一個setTransactionIsolation()方法,允許JDBC客戶端設置Connection對象的事務隔離級別力九。
Connection對象的autoCommit屬性決定什么時候結束事務耍铜。啟用自動提交后,會在每個SQL語句執(zhí)行完畢后自動提交事務跌前。當Connection對象創(chuàng)建時棕兼,默認情況下,事務自動提交是開啟的抵乓。Connection接口中setAutoCommit()方法伴挚,可以禁用事務自動提交。這種情況下灾炭,需要調用Connection接口的commit()方法進行顯式提交事務茎芋,或者調用rollback()方法回滾事務。禁用事務自動提交適用于需要將多個SQL語句作為一個事務提交或者事務由應用服務器管理蜈出。

“老生常談”的事務隔離級別

  1. 臟讀田弥、幻讀、不可重復讀
  • 臟讀铡原,讀取未提交的數(shù)據(jù)導致的偷厦。例如,A事務修改了一條數(shù)據(jù)燕刻,但是未提交修改只泼,此時A事務對數(shù)據(jù)的修改對其他事務是可見的,B事務中能夠讀取A事務未提交的修改卵洗。如果A事務回滾请唱,B事務中讀取的就是不正確的數(shù)據(jù)。
  • 不可重復讀过蹂,(1)A事務中讀取一行數(shù)據(jù)十绑。(2)B事務中修改了該行數(shù)據(jù)。(3)A事務中再次讀取該行數(shù)據(jù)將得到不同的結果酷勺。
  • 幻讀孽惰,(1)A事務中通過WHERE條件讀取若干行。(2)B事務中插入了符合條件的若干條數(shù)據(jù)鸥印。(3)A事務中通過相同的條件再次讀取數(shù)據(jù)時將會讀取到B事務中插入的數(shù)據(jù)勋功。
  1. 幾種事務隔離級別如下:
  • TRANSACTION_NONE:表示驅動不支持事務坦报,不兼容JDBC規(guī)范的驅動程序。
  • TRANSACTION_READ_UNCOMMITTED:允許事務讀取未提交的數(shù)據(jù)狂鞋,可能會出現(xiàn)臟讀片择、不可重復讀、幻讀等現(xiàn)象骚揍。
  • TRANSACTION_READ_COMMITTED:在事務中進行的任何數(shù)據(jù)更改字管,在提交之前對其他事務是不可見的⌒挪唬可以防止臟讀嘲叔,不能解決不可重復讀和幻讀。
  • TRANSACTION_REPEATABLE_READ:能夠解決臟讀和不可重復讀抽活,但是不能解決幻讀硫戈。
  • TRANSACTION_SERIALIZABLE:事務串行執(zhí)行,能夠有效解決臟讀下硕、不可重復讀和幻讀題丁逝,但是并發(fā)效率較低

參考資料

JDBC 4.2規(guī)范文檔:https://download.oracle.com/otndocs/jcp/jdbc-4_2-mrel2-spec/index.html

JDBC在Java 8中相關的功能:https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/jdbc_42.html

JTA規(guī)范文檔:http://download.oracle.com/otndocs/jcp/jta-1.1-spec-oth-JSpec/?submit=Download

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
禁止轉載梭姓,如需轉載請通過簡信或評論聯(lián)系作者霜幼。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市誉尖,隨后出現(xiàn)的幾起案子罪既,更是在濱河造成了極大的恐慌,老刑警劉巖铡恕,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琢感,死亡現(xiàn)場離奇詭異,居然都是意外死亡没咙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門千劈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來祭刚,“玉大人,你說我怎么就攤上這事墙牌∥型裕” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵喜滨,是天一觀的道長捉捅。 經常有香客問我,道長虽风,這世上最難降的妖魔是什么棒口? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任寄月,我火速辦了婚禮,結果婚禮上无牵,老公的妹妹穿的比我還像新娘漾肮。我一直安慰自己,他們只是感情好茎毁,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布克懊。 她就那樣靜靜地躺著,像睡著了一般七蜘。 火紅的嫁衣襯著肌膚如雪谭溉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天橡卤,我揣著相機與錄音扮念,去河邊找鬼。 笑死蒜魄,一個胖子當著我的面吹牛扔亥,可吹牛的內容都是我干的。 我是一名探鬼主播谈为,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼旅挤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伞鲫?” 一聲冷哼從身側響起粘茄,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秕脓,沒想到半個月后柒瓣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡吠架,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年芙贫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傍药。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡磺平,死狀恐怖,靈堂內的尸體忽然破棺而出拐辽,到底是詐尸還是另有隱情拣挪,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布俱诸,位于F島的核電站菠劝,受9級特大地震影響,放射性物質發(fā)生泄漏睁搭。R本人自食惡果不足惜赶诊,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一笼平、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甫何,春花似錦出吹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巍耗,卻和暖如春秋麸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炬太。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工灸蟆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亲族。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓炒考,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霎迫。 傳聞我的和親對象是個殘疾皇子斋枢,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容

  • 以下我是歸納的JDBC知識點圖: 圖上的知識點都可以在我其他的文章內找到相應內容。 JDBC常見面試題 JDBC操...
    Java3y閱讀 1,732評論 0 15
  • 1.定義 JDBC(Java DataBase Connectivity)是Java和數(shù)據(jù)庫之間的一個橋梁知给,是一個...
    唐騦憶閱讀 344評論 0 0
  • 什么是JDBC瓤帚,在什么時候會用到它? JDBC的全稱是Java DataBase Connection涩赢,也就是Ja...
    青青子衿zq閱讀 403評論 0 0
  • JDBC API 給 Java 程序提供了一種訪問一個或者多個數(shù)據(jù)源的途徑戈次,在大多數(shù)情況下,數(shù)據(jù)源是關系型數(shù)據(jù)庫筒扒,...
    zlb閱讀 825評論 0 3
  • 8 MyBatis數(shù)據(jù)源與連接池# 8.1 MyBatis數(shù)據(jù)源DataSource分類## MyBatis數(shù)據(jù)源...
    七寸知架構閱讀 10,274評論 10 106