使用JDBC連接MySQL數(shù)據(jù)庫的5種方式

JDBC介紹

  • JDBC(Java Database Connectivity)是一個(gè)獨(dú)立于特定數(shù)據(jù)庫管理系統(tǒng)脐雪、通用的SQL數(shù)據(jù)庫存取和操作的公共接口(一組API)厌小,定義了用來訪問數(shù)據(jù)庫的標(biāo)準(zhǔn)Java類庫,(java.sql,javax.sql)使用這些類庫可以以一種標(biāo)準(zhǔn)的方法战秋、方便地訪問數(shù)據(jù)庫資源璧亚。
  • JDBC為訪問不同的數(shù)據(jù)庫提供了一種統(tǒng)一的途徑,為開發(fā)者屏蔽了一些細(xì)節(jié)問題脂信。
  • JDBC的目標(biāo)是使Java程序員使用JDBC可以連接任何提供了JDBC驅(qū)動(dòng)程序的數(shù)據(jù)庫系統(tǒng)癣蟋,這樣就使得程序員無需對特定的數(shù)據(jù)庫系統(tǒng)的特點(diǎn)有過多的了解,從而大大簡化和加快了開發(fā)過程狰闪。

JDBC體系結(jié)構(gòu)

JDBC接口(API)包括兩個(gè)層次:

  • 面向應(yīng)用的API:Java API疯搅,抽象接口,供應(yīng)用程序開發(fā)人員使用(連接數(shù)據(jù)庫埋泵,執(zhí)行SQL語句幔欧,獲得結(jié)果)。
  • 面向數(shù)據(jù)庫的API:Java Driver API秋泄,供開發(fā)商開發(fā)數(shù)據(jù)庫驅(qū)動(dòng)程序使用琐馆。

JDBC是sun公司提供一套用于數(shù)據(jù)庫操作的接口,java程序員只需要面向這套接口編程即可恒序。

不同的數(shù)據(jù)庫廠商瘦麸,需要針對這套接口,提供不同實(shí)現(xiàn)歧胁。不同的實(shí)現(xiàn)的集合滋饲,即為不同數(shù)據(jù)庫的驅(qū)動(dòng)。 ————面向接口編程

獲取數(shù)據(jù)庫連接

準(zhǔn)備工作:下載jar包喊巍,可以通過這個(gè)網(wǎng)站下載(Maven倉庫)屠缭,搜索mysql-connector-java,選擇需要的版本崭参,下載jar包即可呵曹,本文使用的是mysql-connector-java-8.0.28

獲取數(shù)據(jù)庫連接的三要素:Driver接口的實(shí)現(xiàn)類,URL以及數(shù)據(jù)庫的用戶名密碼奄喂。

Driver接口

java.sql.Driver接口是所有JDBC驅(qū)動(dòng)程序需要實(shí)現(xiàn)的接口铐殃。這個(gè)接口是提供給數(shù)據(jù)庫廠商使用的,不同數(shù)據(jù)庫廠商提供不同的實(shí)現(xiàn)跨新。在程序中不需要直接去訪問實(shí)現(xiàn)了Driver接口的類富腊,而是由驅(qū)動(dòng)程序管理器類(java.sql.DriverManager)去調(diào)用這些Driver實(shí)現(xiàn)。

  • Oracle的驅(qū)動(dòng):oracle.jdbc.driver.OracleDriver
  • MySQL的驅(qū)動(dòng):com.mysql.jdbc.Driver

注冊與加載驅(qū)動(dòng)

加載驅(qū)動(dòng):加載 JDBC 驅(qū)動(dòng)需調(diào)用Class類的靜態(tài)方法forName()域帐,向其傳遞要加載的JDBC驅(qū)動(dòng)的類名赘被。

Class.forName("com.mysql.jdbc.Driver");

注冊驅(qū)動(dòng):DriverManager類是驅(qū)動(dòng)程序管理器類,負(fù)責(zé)管理驅(qū)動(dòng)程序肖揣。

  • 使用DriverManager.registerDriver(com.mysql.jdbc.Driver)來注冊驅(qū)動(dòng)

URL

JDBC URL 用于標(biāo)識一個(gè)被注冊的驅(qū)動(dòng)程序民假,驅(qū)動(dòng)程序管理器通過這個(gè) URL 選擇正確的驅(qū)動(dòng)程序,從而建立到數(shù)據(jù)庫的連接许饿。

官方文檔中URL的通用格式:

protocol//[hosts][/database][?properties]
  協(xié)議   //主機(jī)名稱 /數(shù)據(jù)庫名稱  ?其他參數(shù)

也有把JDBC URL的標(biāo)準(zhǔn)看成是由三部分組成阳欲,各部分間用冒號分隔:

  • jdbc(協(xié)議):子協(xié)議:子名稱
    • 協(xié)議(jdbc):JDBC URL中的協(xié)議總是jdbc
    • 子協(xié)議:子協(xié)議用于標(biāo)識一個(gè)數(shù)據(jù)庫驅(qū)動(dòng)程序,如:mysql陋率、oracle
    • 子名稱:一種標(biāo)識數(shù)據(jù)庫的方法球化。子名稱可以依不同的子協(xié)議而變化,用子名稱的目的是為了定位數(shù)據(jù)庫提供足夠的信息瓦糟。包含主機(jī)名(對應(yīng)服務(wù)端的ip地址)筒愚,端口號,數(shù)據(jù)庫名

幾種常用的數(shù)據(jù)庫的JDBC URL

  • MySQL的連接URL編寫方式:

    jdbc:mysql://主機(jī)名稱:mysql服務(wù)端口號/數(shù)據(jù)庫名稱?參數(shù)=值&參數(shù)=值
    jdbc:mysql://localhost:3306/test
    jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8(如果JDBC程序與服務(wù)器端的字符集不一致菩浙,會導(dǎo)致亂碼巢掺,那么可以通過參數(shù)指定服務(wù)器端的字符集)
    jdbc:mysql://localhost:3306/test?user=root&password=root
    
  • Oracle 9i的連接URL編寫方式:

    jdbc:oracle:thin:@主機(jī)名稱:oracle服務(wù)端口號:數(shù)據(jù)庫名稱
    jdbc:oracle:thin:@localhost:1521:test
    
  • SQLServer的連接URL編寫方式:

    jdbc:sqlserver://主機(jī)名稱:sqlserver服務(wù)端口號:DatabaseName=數(shù)據(jù)庫名稱
    jdbc:sqlserver://localhost:1433:DatabaseName=test
    

用戶名和密碼

userpassword可以用屬性名=屬性值的方式告訴數(shù)據(jù)庫

也可以通過調(diào)用DriverManager類的getConnection(url, user, password)方法將用戶名和密碼告訴數(shù)據(jù)庫,與數(shù)據(jù)庫建立連接劲蜻。

連接數(shù)據(jù)庫的方式

聲明:不是說有很多種連接方式陆淀,而是為了展示一步一步對連接數(shù)據(jù)庫的寫法進(jìn)行迭代,為了區(qū)分先嬉,才說成有多種方式轧苫,最后我們會得出一個(gè)最終(最優(yōu))的寫法

連接方式一

@Test
public void testConnection() throws SQLException {

    // 1. 獲取Driver實(shí)現(xiàn)類對象,使用數(shù)據(jù)庫廠商提供的類
    Driver driver = new com.mysql.jdbc.Driver();

    /*
        * jdbc:mysql    協(xié)議
        * localhost     ip地址
        * 3306          默認(rèn)的mysql的端口號
        * test          test數(shù)據(jù)庫
        * */
    String url = "jdbc:mysql://localhost:3306/test";
    Properties info = new Properties();

    // 將用戶名和密碼封裝在Properties中
    info.setProperty("user", "root");
    info.setProperty("password", "root");

    Connection conn = driver.connect(url, info);
    System.out.println(conn);
}

注意疫蔓,這里有個(gè)問題含懊,如果使用的連接器(mysql-connector-java)版本在6以下,使用的驅(qū)動(dòng)類就是com.mysql.jdbc.Driver衅胀,如果連接器版本是6以及6以上岔乔,使用的驅(qū)動(dòng)類就是com.mysql.cj.jdbc.Driver,如果依然使用過的是com.mysql.jdbc.Driver滚躯,那么就會有個(gè)警告性的錯(cuò)誤提示:

Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

出現(xiàn)這個(gè)提示雏门,并不是說com.mysql.jdbc.Driver完全不能使用嘿歌,而是不推薦使用,官方更推薦使用com.mysql.cj.jdbc.Driver剿配。使用com.mysql.jdbc.Driver也可以連接上數(shù)據(jù)庫并進(jìn)行操作搅幅,如果使用的連接器是6以上的版本阅束,還是按照官方推薦的呼胚,使用com.mysql.cj.jdbc.Driver較好。

連接器版本在6以下息裸,com.mysql.jdbc.Driver類的源碼:

// com.mysql.jdbc.Driver實(shí)現(xiàn)了java.sql.Driver
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

連接器版本在6以上蝇更,com.mysql.jdbc.Driver類的源碼:

// com.mysql.jdbc.Driver繼承了com.mysql.cj.jdbc.Driver,所以com.mysql.jdbc.Driver類依然可以使用呼盆,但是不推薦年扩。
public class Driver extends com.mysql.cj.jdbc.Driver {
    public Driver() throws SQLException {
    }

    static {
        System.err.println("Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.");
    }
}

com.mysql.cj.jdbc.Driver的源碼:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

注意事項(xiàng)

如果使用com.mysql.cj.jdbc.Driver驅(qū)動(dòng)類,URL中沒有設(shè)置useSSL=false访圃,則會在連接數(shù)據(jù)庫的時(shí)候出現(xiàn)以下提示:

WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements
SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate
property is set to 'false'.You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate
verification.

URL中如果沒有設(shè)置serverTimezone=Asia/Shanghai厨幻,則會在連接數(shù)據(jù)庫的時(shí)候出現(xiàn)以下提示:

The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

為什么不設(shè)置serverTimezone=UTC,是因?yàn)閁TC(世界標(biāo)準(zhǔn)時(shí)間)和北京時(shí)間相差8個(gè)小時(shí)腿时,所以具體設(shè)置哪個(gè)時(shí)區(qū)的時(shí)間况脆,請根據(jù)實(shí)際需求設(shè)置。

我在例子中URL并沒有設(shè)置useSSL和serverTimezone批糟,并沒有報(bào)錯(cuò)格了。我也沒有深究原因(我猜測是沒有使用框架),如果出現(xiàn)了上述提到的錯(cuò)誤徽鼎,那就加上相應(yīng)的參數(shù)即可盛末。

連接方式二

方式一中的代碼,我直接使用了new com.mysql.jdbc.Driver()第三方的API否淤,程序的依賴性強(qiáng)悄但。

現(xiàn)在對方式一進(jìn)行迭代:

// 方式二:對方式一的迭代,在如下程序中不出現(xiàn)第三方的api石抡,使得程序具有更好的可移植性
@Test
public void testConnection2() throws Exception {
    // 1. 獲取Driver實(shí)現(xiàn)類對象檐嚣,使用反射
    Class<?> clazz = Class.forName("com.mysql.jdbc.Driver");
    Driver driver = (Driver) clazz.newInstance();

    // 2. 提供鏈接需要的用戶名和密碼
    String url = "jdbc:mysql://localhost:3306/test";

    // 3. 提供鏈接需要的用戶名和密碼
    Properties info = new Properties();
    info.setProperty("user", "root");
    info.setProperty("password", "root");

    // 4. 獲取鏈接
    Connection conn = driver.connect(url, info);
    System.out.println(conn);

}

連接方式三

對方式二的迭代:

// 方式三:使用DriverManager替換Driver
@Test
public void testConnection3() throws Exception {
    // 1. 獲取Driver實(shí)現(xiàn)類對象,使用反射
    Class<?> clazz = Class.forName("com.mysql.jdbc.Driver");
    Driver driver = (Driver) clazz.newInstance();

    // 2. 提供另外三個(gè)連接的基本信息
    String url = "jdbc:mysql://localhost:3306/test";
    String user = "root";
    String password = "root";

    // 3. 注冊驅(qū)動(dòng)
    DriverManager.registerDriver(driver);

    // 4. 獲取鏈接
    Connection conn = DriverManager.getConnection(url, user, password);
    System.out.println(conn);
}

DriverManager顧名思義是驅(qū)動(dòng)管理類汁雷,使用它比直接使用Driver更為方便净嘀。

連接方式四

對方式三進(jìn)行迭代:

// 方式四:可以只是加載驅(qū)動(dòng),不用顯示的注冊驅(qū)動(dòng)了侠讯。
@Test
public void testConnection4() throws Exception {
    // 1. 獲取Driver實(shí)現(xiàn)類對象
    Class.forName("com.mysql.jdbc.Driver");
    //相較于方式3挖藏,可以省略注冊驅(qū)動(dòng)的操作
    // 2. 注冊驅(qū)動(dòng)
    // DriverManager.registerDriver(driver);
    // 為什么?
    /*
        在 mysql的Driver實(shí)現(xiàn)類中厢漩,聲明了如下的操作:
        static {
            try {
                DriverManager.registerDriver(new Driver());
            } catch (SQLException var1) {
                throw new RuntimeException("Can't register driver!");
            }
        }
         */

    // 2. 提供另外三個(gè)連接的基本信息
    String url = "jdbc:mysql://localhost:3306/test";
    String user = "root";
    String password = "root";

    // 3. 獲取鏈接
    Connection conn = DriverManager.getConnection(url, user, password);
    System.out.println(conn);
}

連接方式五(最終方案)

在src目錄下新建配置文件jdbc.properties膜眠,將數(shù)據(jù)庫連接需要的4個(gè)基本信息聲明在配置文件中:

user=root
password=root
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver

注意,如果使用的連接器(mysql-connector-java)是6及6以上的版本,driverClass應(yīng)使用com.mysql.cj.jdbc.Driver宵膨。

// 方式五:終極方案架谎,將數(shù)據(jù)庫連接需要的4個(gè)基本信息聲明在配置文件中,通過讀取配置文件的方式獲取鏈接
@Test
public void getConnection() throws Exception {
    // 1. 讀取配置文件中的4個(gè)基本信息
    InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
    Properties pros = new Properties();
    pros.load(is);

    String user = pros.getProperty("user");
    String password = pros.getProperty("password");
    String url = pros.getProperty("url");
    String driverClass = pros.getProperty("driverClass");

    // 2. 加載驅(qū)動(dòng)
    Class.forName(driverClass);

    // 3. 獲取鏈接
    Connection conn = DriverManager.getConnection(url, user, password);
    System.out.println(conn);

}

使用這種方式的好處:

  • 實(shí)現(xiàn)了數(shù)據(jù)與代碼的分離辟躏,實(shí)現(xiàn)了解耦谷扣。
  • 如果需要修改配置文件中的信息,可以避免程序重新編譯打過捎琐。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末会涎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瑞凑,更是在濱河造成了極大的恐慌末秃,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籽御,死亡現(xiàn)場離奇詭異练慕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)技掏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門铃将,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人零截,你說我怎么就攤上這事麸塞。” “怎么了涧衙?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵哪工,是天一觀的道長。 經(jīng)常有香客問我弧哎,道長雁比,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任撤嫩,我火速辦了婚禮偎捎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘序攘。我一直安慰自己茴她,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布程奠。 她就那樣靜靜地躺著丈牢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞄沙。 梳的紋絲不亂的頭發(fā)上己沛,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天慌核,我揣著相機(jī)與錄音,去河邊找鬼申尼。 笑死垮卓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的师幕。 我是一名探鬼主播粟按,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼们衙!你這毒婦竟也來了钾怔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蒙挑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后愚臀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忆蚀,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年姑裂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了馋袜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舶斧,死狀恐怖欣鳖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茴厉,我是刑警寧澤泽台,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站矾缓,受9級特大地震影響怀酷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗜闻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一蜕依、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧琉雳,春花似錦样眠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锯茄,卻和暖如春厢塘,著一層夾襖步出監(jiān)牢的瞬間茶没,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工晚碾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抓半,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓格嘁,卻偏偏與公主長得像笛求,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子糕簿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容