BD1 - Java 3-4 JDBC - 配置文件 連接池

此心不動税稼,隨機而動

Java第12天上午

上午主要復習了JDBC

詳細內容可參見:
7.21 JDBC 學習總結

以下總結補充:

JDBC用途

使用JDBC來操作數(shù)據(jù)庫用到的類:


遍歷數(shù)據(jù)庫的大致步驟:


連接數(shù)據(jù)庫的大致步驟

不遍歷的話 則:


步驟

PreparedStatement優(yōu)勢絕不僅僅是更靈活的參數(shù)化查詢
請參見:PreparedStatement VS Statement

上午完成的經(jīng)典代碼:(遍歷數(shù)據(jù))

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        String Driver = "com.mysql.jdbc.Driver";
        // 對應 第二步 
        String url = "jdbc:mysql://localhost:3306/itcast";
        String user = "root";
        String password = "root";
        
        try{
            // 第一步 先加載注冊JDBC的驅動類
            Class.forName(Driver);
            // 第二步 提供JDBC連接的url
            
            // 第三步 創(chuàng)建數(shù)據(jù)庫的連接
            conn = DriverManager.getConnection(url, user, password);
            // 第四步 創(chuàng)建一個statement對象
            stmt = conn.createStatement();
            // 第五步 執(zhí)行sql語句
            rs = stmt.executeQuery("select * from student");
            // 第六步 循環(huán)遍歷處理結果
            while(rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getString("birth").subSequence(0, 4));
            }
        } catch(ClassNotFoundException s){
            s.printStackTrace();
        } catch (SQLException e){
            e.printStackTrace();
        } finally {
            // 第七步 關閉JDBC對象
            try {
                if(rs != null) {
                    rs.close();
                 }
                if(stmt != null)(       
                    stmt.close();
                }
                if(conn != null){
                    conn.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

上午完成的經(jīng)典代碼:(插入數(shù)據(jù))

import java.sql.*;

public class TestDML {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        
        String Driver = "com.mysql.jdbc.Driver";
        // 對應 下面第二步 
        String url = "jdbc:mysql://localhost:3306/itcast";
        String user = "root";
        String password = "root";
        try{
            // 第一步 先加載注冊JDBC的驅動類
            Class.forName(Driver);
            // 第二步 提供JDBC連接的url
            
            // 第三步 創(chuàng)建數(shù)據(jù)庫的連接
            conn = DriverManager.getConnection(url, user, password);
            // 第四步 創(chuàng)建一個statement對象
            //pstmt = conn.prepareStatement("insert into student values(7,'你好','男',17)");
            pstmt = conn.prepareStatement("insert into student values(?,?,?,?,?)");
            pstmt.setInt(1, 0);
            pstmt.setString(2, "王33");
            pstmt.setString(3, "男");
            pstmt.setInt(4, 25);
            pstmt.setString(5, "2017");
            pstmt.executeUpdate();          
        } catch(ClassNotFoundException s){
            s.printStackTrace();
        } catch (SQLException e){
            e.printStackTrace();
        } finally {
            // 第七步 關閉JDBC對象
            try {
                if(pstmt != null) {
                    pstmt.close();
                }
                if(conn != null) {
                    conn.close();
                }           
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

下午主要學習了配置文件和連接池

Java配置文件

在上午代碼基礎上 我們考慮進一步優(yōu)化代碼結構

給定這樣的數(shù)據(jù)庫:


數(shù)據(jù)庫

先來看之前創(chuàng)建連接的結構:

// 第一步 先加載注冊JDBC的驅動類
String Driver = "com.mysql.jdbc.Driver";
Class.forName(Driver);
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";
// 第三步 創(chuàng)建數(shù)據(jù)庫的連接
conn = DriverManager.getConnection(url, user, password);

可見 我們每創(chuàng)建一個連接 就需要重現(xiàn)以上代碼

并且在開發(fā)時 有些參數(shù)是經(jīng)常改變的
比如操作數(shù)據(jù)庫時 我們可能連接本地的數(shù)據(jù)庫 那么IP 、數(shù)據(jù)庫名稱棚点、表名稱和數(shù)據(jù)庫主機等信息是我們本地的舔琅。

要使得操作數(shù)據(jù)的模塊具有通用性碗硬,那么以上信息就不能寫死在程序里扛或。通常我們的做法是用配置文件來解決

關于更多java配置文件說明 請看:.properties Java 配置文件

所以先來新建一個properties (Java配置文件):
先右擊src文件夾 新建一個File

配置文件 - 新建一個File

選File 再點擊Next:


File

File名稱設置為:db.properties


db.properties

db.properties 文件新建成功:


新建成功

可以點擊右邊的Add在彈窗中輸入key - value 數(shù)據(jù):


輸入key - value 數(shù)據(jù)

比如 我們輸入 user - root 點擊 Finish:


輸入-1
輸入-2

點擊左下角的Source:


輸入-3

即我們也可以在Source中直接輸入:(推薦做法)

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/itcast
user=root
password=root

(左邊是key 右邊是value)

輸入結果如圖:


輸入結果

即目前我們成功把:

// 第一步 先注冊加載JDBC的驅動類
String Driver = "com.mysql.jdbc.Driver";
Class.forName(Driver);
// 第二步 提供JDBC連接的url
String url = "jdbc:mysql://localhost:3306/itcast";
String user = "root";
String password = "root";

信息寫到了 配置文件中


下面我們來看如何調用配置信息:
同樣在 src 目錄下 新建一個 JdbcUtil 類:

新建JdbcUtil
新建JdbcUtil

直接給出 JdbcUtil.java 代碼:

import java.io.IOException;
import java.util.Properties;
import java.sql.*;

public class JdbcUtil {

    private static String driver;
    private static String url;
    private static String uesrname;
    private static String password;
    
    static {
        try{
            Properties p = new Properties();
            p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
            driver = p.getProperty("driver");
            url = p.getProperty("url");
            uesrname = p.getProperty("user");
            password = p.getProperty("password");
            Class.forName(driver);
        }catch(IOException e){
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    public static Connection createConnection(){
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, uesrname, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
    
    public static void close(Connection conn, Statement stat,ResultSet rs) {
        try {
            if(rs != null){
                rs.close();
            }
            if(stat != null){
                stat.close();
            }
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
}

代碼說明:
1 4個成員變量分別用來接收 從配置文件讀到的內容

private static String driver;
private static String url;
private static String uesrname;
private static String password;

對應配置文件中 左邊的4個key:


對應

2 中間的 靜態(tài)代碼塊 完成 :

  • 獲取配置文件的value:


    獲取配置文件的value
  • 注冊加載JDBC的驅動類:

Class.forName(driver);

注意

Properties p = new Properties();
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));

load方法可以從 .properties屬性文件(這里是db.properties) 對應的文件輸入流中绵咱,加載屬性列表到Properties類對象(這里是p),即通過對上面的 properties 文件進行裝載來獲取該文件中的所有鍵 - 值對熙兔。以供 getProperty ( String key) 來搜索悲伶。

另外Thread.currentThread().getContextClassLoader().getResourceAsStream() 請看:讀取配置文件Properties的一種方案

另外補充:
Java中普通代碼塊,構造代碼塊黔姜,靜態(tài)代碼塊區(qū)別及代碼示例

3 createConnection 方法:(創(chuàng)建數(shù)據(jù)庫的連接)

public static Connection createConnection(){
    Connection conn = null;
    try {
        conn = DriverManager.getConnection(url, uesrname, password);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return conn;
}
下面測試

在src 下新建一個Test.java文件:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Test {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        conn = JdbcUtil.createConnection();
        String sql = "select * from student";
        
        try{
            stat = conn.createStatement();
            rs = stat.executeQuery(sql);
            while(rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(conn, stat, rs);
        }
        
    }
}

其中拢切,我們以后可這樣創(chuàng)建連接:

conn = JdbcUtil.createConnection();

(即利用JdbcUtil中的方法創(chuàng)建連接)

其中,我們也可以這樣關閉資源:

JdbcUtil.close(conn, stat, rs);

即利用JdbcUtil中的close()方法關閉資源

JdbcUtil中的close()方法:

public static void close(Connection conn, Statement stat,ResultSet rs) {
    try {
        if(rs != null){
            rs.close();
        }
        if(stat != null){
            stat.close();
        }
        if(conn != null){
            conn.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

運行一下Test.java文件 可見成功打痈殉场:


運行結果

連接池

我們來考慮下通過配置文件創(chuàng)建連接的性能,在JdbcUtil類的createConnection()方法中利用系統(tǒng)的currentTimeMillis()函數(shù)獲取前后用時:


獲取前后用時

運行可見用時476ms:
(不同電腦性能有差異五慈,您的時間可能不同)


QQ圖片20170807211826.png

476ms已經(jīng)不算少了 試想如果創(chuàng)建多個Connection 那么用時會很長纳寂,足以嚴重影響性能。

所以泻拦,我們提出連接池概念:

更多連接池概念請見:
1 - Java連接池詳解
2 - 幾個主流的Java連接池整理

一下不理解很正常毙芜,先有個概念:池技術是為了優(yōu)化服務器應用程序的性能、提高程序執(zhí)行效率和降低系統(tǒng)資源開銷争拐。

考慮下連接池的設計:
連接池(connection pool)

  • 使用集合 將Connection對象放入List中腋粥,反復使用
  • 連接池的初始化
    • 事先放入多個連接對象
  • 從連接池中獲取連接對象
    • 如果池中無可用連接,則創(chuàng)建一個新的
    • 如果池中有可用連接架曹,則將池中最后一個返回隘冲,同時,將該連接從池中remove绑雄,表示正在使用
  • 關閉連接
    • 不是真正的關閉展辞,而是將用完的放回去

新建一個com.pool包 在包下新建 DBConnPool.java:

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import com.hkj.JdbcUtil;

public class DBConnPool {

    // 連接對象
    private static List<Connection> pool;
    // 最大連接數(shù)
    private static final int POOL_MAX_SIZE = 100;
    // 最小連接數(shù)
    private static final int POOL_MIN_SIZE = 10;
    
    public DBConnPool(){
        initPool();
    }
    
    // 初始化連接池 讓池中的連接數(shù)達到最小值
    public void initPool(){
        if(pool == null){
            pool = new ArrayList<Connection>();
        }
        while(pool.size() < POOL_MIN_SIZE){
            pool.add(JdbcUtil.createConnection());
            System.out.println("初始化池,池中連接數(shù):"+pool.size());
        }
    }
    
    // 從池取最后一個連接 
    public synchronized Connection getConnection(){
        Connection conn = null;
        int last_index = 0;
        if(pool.size() == 0) {
            pool.add(JdbcUtil.createConnection());          
        }
        last_index = pool.size()-1;
        conn = pool.get(last_index);
        pool.remove(last_index);
        return conn;
    }
    
    // 將連接池放回池中
    public synchronized void close(Connection conn){
        if(pool.size() >= POOL_MAX_SIZE){
            try {
                if(conn != null){
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            pool.add(conn);
        }
    }
}

注意:


初始化連接池

在此初始化方法中 循環(huán)add 以讓池中的連接數(shù)達到最小值

TestPool.java代碼:

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.pool.DBConnPool;

public class TestPool {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;

        DBConnPool dbpool = new DBConnPool();
        conn = dbpool.getConnection();
        String sql = "select * from student";
        
        try{
            stat = conn.createStatement();
            rs = stat.executeQuery(sql);
            while(rs.next()){
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            dbpool.close(conn);
        }
        
    }
}

主要代碼——新建連接池對象:

DBConnPool dbpool = new DBConnPool();

利用連接池對象的getConnection()獲取一個連接:

conn = dbpool.getConnection();

利用連接池對象的close()將連接池放回池中:

dbpool.close(conn);

一定注意 close并不是真的關掉 而是放回池:


close 放回池
拓展閱讀:

Java中Synchronized的用法


世界上所有的追求都是因為熱愛
一枚愛編碼 愛生活 愛分享的IT信徒
— hongXkeX

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末万牺,一起剝皮案震驚了整個濱河市罗珍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脚粟,老刑警劉巖覆旱,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異核无,居然都是意外死亡扣唱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來画舌,“玉大人堕担,你說我怎么就攤上這事∏簦” “怎么了霹购?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長朋腋。 經(jīng)常有香客問我齐疙,道長,這世上最難降的妖魔是什么旭咽? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任贞奋,我火速辦了婚禮,結果婚禮上穷绵,老公的妹妹穿的比我還像新娘轿塔。我一直安慰自己,他們只是感情好仲墨,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布勾缭。 她就那樣靜靜地躺著,像睡著了一般目养。 火紅的嫁衣襯著肌膚如雪俩由。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天癌蚁,我揣著相機與錄音幻梯,去河邊找鬼。 笑死努释,一個胖子當著我的面吹牛碘梢,可吹牛的內容都是我干的。 我是一名探鬼主播洽洁,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼痘系,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饿自?” 一聲冷哼從身側響起汰翠,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昭雌,沒想到半個月后复唤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡烛卧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年佛纫,在試婚紗的時候發(fā)現(xiàn)自己被綠了妓局。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡呈宇,死狀恐怖好爬,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情甥啄,我是刑警寧澤存炮,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蜈漓,受9級特大地震影響穆桂,放射性物質發(fā)生泄漏。R本人自食惡果不足惜融虽,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一享完、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧有额,春花似錦般又、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至句狼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間热某,已是汗流浹背腻菇。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昔馋,地道東北人筹吐。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像秘遏,于是被迫代替她去往敵國和親丘薛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理邦危,服務發(fā)現(xiàn)洋侨,斷路器,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法倦蚪,類相關的語法希坚,內部類的語法,繼承相關的語法陵且,異常的語法裁僧,線程的語...
    子非魚_t_閱讀 31,632評論 18 399
  • 本文包括傳統(tǒng)JDBC的缺點連接池原理自定義連接池開源數(shù)據(jù)庫連接池DBCP連接池C3P0連接池Tomcat內置連接池...
    廖少少閱讀 16,745評論 0 37
  • “《情書》是由巖井俊二自編自導的的日本純愛電影,由中山美穗、豐川悅司聊疲、柏原崇主演茬底,于1995年3月25日首映。電影...
    ConnecToMe閱讀 292評論 4 4
  • tribbie閱讀 303評論 4 7