Data Source與數(shù)據(jù)庫連接池簡介(JDBC簡介)
DataSource是作為DriverManager的替代品而推出的,DataSource 對象是獲取連接的首選方法。
起源
為何放棄DriverManager
DriverManager負責管理驅(qū)動程序,并且使用已注冊的驅(qū)動程序進行連接。
//1、注冊驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
//數(shù)據(jù)庫連接所需參數(shù)
String user = "root";
String password = "123456";
String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";
//2、獲取連接對象
Connection conn = DriverManager.getConnection(url, user, password);使用DriverManager的一般形式如上面代碼所示
直接使用DriverManager的這種形式,通常需要將驅(qū)動程序硬編碼到項目中(JDBC4.0后可以自動注冊驅(qū)動程序)
而且最重要的是DriverManager的getConnection方法獲取的連接,是建立與數(shù)據(jù)庫的連接,是建立與數(shù)據(jù)庫的連接,是建立與數(shù)據(jù)庫的連接。
但是建立與數(shù)據(jù)庫的連接是一項較耗資源的工作,頻繁的進行數(shù)據(jù)庫連接建立操作會產(chǎn)生較大的系統(tǒng)開銷。
隨著企業(yè)級應用復雜度的提升以及對性能要求的提高,這一點是難以接受的。
連接池
既然每次使用時都重新建立與數(shù)據(jù)庫之間的連接,會產(chǎn)生較大的系統(tǒng)開銷
是否可以事先創(chuàng)建一些連接備用,當需要時,從這些連接中選擇一個提供出去;當連接使用完畢后,并不是真正的關(guān)閉,而是將這些數(shù)據(jù)狀態(tài)還原,然后繼續(xù)等待下一個人使用?
比如滑雪場會租賃雪具滑雪服等,如果你不是資深玩家,你沒有必要浪費錢買,即使你不差錢,每次去滑雪場都不能輕裝上陣,每次都要攜帶很多裝備,也是一件麻煩事。
這種沒必要的花費或者麻煩其實都是一種開銷。
連接池的核心與租用的理念有類似的點,重復使用可以提高連接的利用率,減少開銷(當然連接池的使用并不需要你花費一筆租金)
連接的持有是消耗空間的,但是現(xiàn)在絕大多數(shù)場景下,磁盤空間并沒有那么金貴,我們更關(guān)心的是性能,所以空間換取時間,連接池的邏輯被廣泛應用。
數(shù)據(jù)源
DriverManager只是建立與數(shù)據(jù)庫之間的連接,如何才能將連接池的概念應用其中?
一種很自然的方式就是提供一個薄層的封裝,建立一個中間層,這個中間層將DriverManager生成的連接,組織到連接池中,然后從池中提供連接。

Data Source就是DriverManager的一種替代角色,對外呈現(xiàn)就類似于一個DriverManager,擁有對外提供連接的能力直接使用DriverManager,驅(qū)動程序與管理器是“服務者---管理者”的形式,借助于管理者才能提供服務。Data Source將驅(qū)動程序的概念淡化了,突出驅(qū)動程序能夠提供的服務與能力,將驅(qū)動程序提供的服務與能力抽象為Data Source數(shù)據(jù)源這一角色。

DataSource中獲取的連接來自于連接池中,而池中的連接根本也還是從DriverManager獲取而來
有了數(shù)據(jù)源這一中間層,就可以實現(xiàn)連接池和分布式事務的管理。
對外呈現(xiàn)DataSource就是類似于DriverManager的一個存在。
DataSource的形式是JNDI (Java Naming Directory Interface)
DataSource是JNDI資源的一種,那么到底什么是JNDI呢
此處不過多解釋,可以簡單認為JNDI是類似這樣一個東西:
一個哈希表,類型為<String,Object>
JNDI的兩個最主要操作:bind和lookup。bind操作負責往哈希表里存對象,lookup則根據(jù)這個鍵值字符串往外取對象。
開發(fā)人員可以使用鍵值——也就是一個字符串名稱——來獲取某個對象。
簡言之就是可以給一個對象命名,然后可以通過名稱找到這個對象。
數(shù)據(jù)源的概念在應用程序與數(shù)據(jù)庫連接之間插入了一個中間層,進而可以實現(xiàn)連接池以及事務管理,并且以JNDI的形式,也能夠以非常方便的形式使用。
實現(xiàn)
核心架構(gòu)
關(guān)于數(shù)據(jù)源有以下幾個核心的接口
CommonDataSource接口定義了 DataSource、XADataSource 和 ConnectionPoolDataSource 之間公用的方法。
DataSource 是 官方定義的獲取 connection 的接口, ConnectionPoolDataSource 是官方定義的從 connection pool 中拿 connection 的接口,XADataSource是定義的用來獲取分布式事務連接的接口
也就是分為了三個方向,基本實現(xiàn),連接池,事務

對于ConnectionPoolDataSource的使用方案應該是下面所示
對于Connection Pool的實現(xiàn),借助于ConnectionPoolDataSource,進而獲取PooledConnection ,然后獲取連接,這是一種標準做法

但是有的時候 事情的發(fā)展或許并不一定如規(guī)劃的那般發(fā)展
很多的工具類僅僅實現(xiàn)DataSource了,也一并實現(xiàn)連接池以及事務的能力,接口就在那里,我直接實現(xiàn)一個強大的實現(xiàn)類,也沒什么問題
DataSource
這是一個工廠對象,用于提供到此 DataSource 對象所表示的物理數(shù)據(jù)源的連接。
作為 DriverManager 工具的替代項,DataSource 對象是獲取連接的首選方法。
實現(xiàn) DataSource 接口的對象通常在基于 JavaTM Naming and Directory Interface (JNDI) API 的命名服務中注冊。
DataSource 接口由驅(qū)動程序供應商實現(xiàn)。共有三種類型的實現(xiàn):
- 基本實現(xiàn) - 生成標準的 Connection 對象
- 連接池實現(xiàn) - 生成自動參與連接池的 Connection 對象。此實現(xiàn)與中間層連接池管理器一起使用。
- 分布式事務實現(xiàn) - 生成一個 Connection 對象,該對象可用于分布式事務,大多數(shù)情況下總是參與連接池。此實現(xiàn)與中間層事務管理器一起使用,大多數(shù)情況下總是與連接池管理器一起使用。
DataSource 對象的屬性在必要時可以修改。
例如,如果將數(shù)據(jù)源移動到另一個服務器,則可更改與服務器相關(guān)的屬性。其優(yōu)點在于,由于可以更改數(shù)據(jù)源的屬性,所以任何訪問該數(shù)據(jù)源的代碼都無需更改。
通過 DataSource 對象訪問的驅(qū)動程序本身不會向 DriverManager 注冊。
通過lookup操作獲取 DataSource 對象,然后使用該對象創(chuàng)建 Connection 對象。
使用基本的實現(xiàn),通過 DataSource 對象獲取的連接與通過 DriverManager 設施獲取的連接相同。
數(shù)據(jù)源的實現(xiàn)必須提供public的無參的構(gòu)造函數(shù)。
API
DataSource只有兩個方法(確切的說是一個方法的兩個重載版本),用于建立與此 DataSource 對象所表示的數(shù)據(jù)源的連接。
- Connection getConnection()
- Connection getConnection(String username, String password)
小結(jié)
DriverManager用于管理驅(qū)動程序并且提供數(shù)據(jù)庫的直連,頻繁的創(chuàng)建和消耗連接增加系統(tǒng)大量開銷,并且將數(shù)據(jù)庫連接直接暴露。
數(shù)據(jù)源的概念就是為了在應用程序和DriverManager創(chuàng)建的數(shù)據(jù)庫直接連接之間插入一個中間層
借助于中間層,應用程序與數(shù)據(jù)庫的連接兩者之間完成了解耦,也能夠?qū)?shù)據(jù)庫的真實連接進行隱藏;
一旦解耦,通過中間層間接調(diào)用,類似代理模式,就可以添加更多的服務---連接池以及分布式事務。
數(shù)據(jù)源相關(guān)接口有三個,但是很多是僅僅實現(xiàn)了DataSource接口
而對于連接池本質(zhì)就是一個容器,負責管理創(chuàng)建好的數(shù)據(jù)庫連接。
連接池與數(shù)據(jù)源邏輯上是兩回事,但是在實現(xiàn)層面的代碼中DataSource的實現(xiàn)類往往都具有了連接池以及連接池管理方面的功能。
所以有些時候,DataSource到底是理解成數(shù)據(jù)源?還是javax.sql.DataSource?還是指的一個實現(xiàn)?還是一個實現(xiàn)了數(shù)據(jù)庫連接池的實現(xiàn)?(經(jīng)常一個實現(xiàn)了DataSource的并且提供了連接池功能的實現(xiàn),會被叫做數(shù)據(jù)庫連接池)
應用
Java作為一種廣泛使用的開發(fā)語言,自然不需要我們自己實現(xiàn)DataSource,一些大廠已經(jīng)幫我們實現(xiàn)了
比如:DBCP ,C3P0 ,druid
下面的三張圖展示了類繼承結(jié)構(gòu),可以看得出來他們實現(xiàn)的接口



目前推薦使用ALI的Druid,http://druid.io/
maven中央倉庫: http://central.maven.org/maven2/com/alibaba/druid/
Druid是一個開源項目,源碼托管在github上,源代碼倉庫地址是 https://github.com/alibaba/druid。
Wiki首頁:
https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
與其他主流對比

數(shù)據(jù)庫連接池示例
如下一個簡單的演示
package jdbc;
import com.alibaba.druid.pool.DruidDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.apache.commons.dbcp2.BasicDataSource;
public class MyDataSource {
public static void main(String[] args) throws Exception {
String user = "root";
String password = "123456";
String url = "jdbc:mysql://localhost:3306/sampledb?useUnicode=true&characterEncoding=utf-8";
//1.獲取連接
// Connection conn = getDHCPConnection(user,password,url);
//Connection conn = getC3P0Connection(user,password,url);
Connection conn = getDruidConnection(user, password, url);
String sql = "select * from student limit 0,10";
//2、獲得sql語句執(zhí)行對象
Statement stmt = conn.createStatement();
//3、執(zhí)行并保存結(jié)果集
ResultSet rs = stmt.executeQuery(sql);
//4、處理結(jié)果集
while (rs.next()) {
System.out.print("id:" + rs.getInt(1));
System.out.print(",姓名:" + rs.getString(2));
System.out.print(",年齡:" + rs.getInt(3));
System.out.println(",性別:" + rs.getString(4));
}
conn.close();
stmt.close();
rs.close();
}
public static Connection getDruidConnection(String user, String password, String url)
throws Exception {
DruidDataSource ds = new DruidDataSource();
ds.setUsername(user);
ds.setPassword(password);
ds.setUrl(url);
ds.setDriverClassName("com.mysql.jdbc.Driver");
return ds.getConnection();
}
public static Connection getC3P0Connection(String user, String password, String url)
throws Exception {
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setUser(user);
cpds.setPassword(password);
cpds.setJdbcUrl(url);
cpds.setDriverClass("com.mysql.jdbc.Driver");
return cpds.getConnection();
}
public static Connection getDHCPConnection(String user, String password, String url)
throws Exception {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
Connection connection = dataSource.getConnection();
return connection;
}
}
總結(jié)
數(shù)據(jù)源作為DriverManager的替代者,用于獲取數(shù)據(jù)庫連接,你應該總是使用DataSource
DataSource是應用程序與數(shù)據(jù)庫連接的一個抽象的中間層,是一個接口
對于DataSource已經(jīng)有了很多優(yōu)秀的實現(xiàn),其中較為突出的為Druid,建議使用,Druid不僅僅提供了連接池的功能還提供了其他比如監(jiān)控等功能,非常強大。
對于數(shù)據(jù)源的應用,除了用戶名密碼url還有其他的一些屬性信息,比如最大連接數(shù),建立連接的最大等待時間等,不同的連接池略微有出入,可以查看手冊。
對于DataSource的一些實現(xiàn),經(jīng)常被叫做數(shù)據(jù)庫連接池,比如Druid官方文檔中說“Druid是Java語言中最好的數(shù)據(jù)庫連接池“,本質(zhì)核心就是DataSource的一個實現(xiàn)類,作為中間層使用,并且基本上都提供了附帶的其他的服務,也就是說不僅僅實現(xiàn)了核心建筑,也基于核心之上構(gòu)建了很多的外圍建設。
到此這篇關(guān)于Data Source與數(shù)據(jù)庫連接池簡介(JDBC簡介)的文章就介紹到這了,更多相關(guān)數(shù)據(jù)庫連接池Data Source內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java ArrayBlockingQueue阻塞隊列的實現(xiàn)示例
ArrayBlockingQueue是一個基于數(shù)組實現(xiàn)的阻塞隊列,本文就來介紹一下java ArrayBlockingQueue阻塞隊列的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2024-02-02
Java輸入三個整數(shù)并把他們由小到大輸出(x,y,z)
這篇文章主要介紹了輸入三個整數(shù)x,y,z,請把這三個數(shù)由小到大輸出,需要的朋友可以參考下2017-02-02
詳解Java 序列化與反序列化(Serialization)
這篇文章主要介紹了Java 序列化與反序列化(Serialization),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習 吧2019-03-03
解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題
這篇文章主要介紹了解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
mybatis?collection和association的區(qū)別解析
這篇文章主要介紹了mybatis?collection解析以及和association的區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
SpringBoot實現(xiàn)對超大文件進行異步壓縮下載的使用示例
在Web應用中,文件下載功能是一個常見的需求,本文介紹了SpringBoot實現(xiàn)對超大文件進行異步壓縮下載的使用示例,具有一定的參考價值,感興趣的可以了解一下,2023-09-09
Java Swing實現(xiàn)簡單的體重指數(shù)(BMI)計算器功能示例
這篇文章主要介紹了Java Swing實現(xiàn)簡單的體重指數(shù)(BMI)計算器功能,涉及Java Swing窗口組件布局、響應及數(shù)值運算相關(guān)操作技巧,需要的朋友可以參考下2017-12-12

