MySql & JDBC & 鏈接池 & 總結

鏈接池:解決資源浪費,提升代碼性能。
本小節目標:
使用DBCP,C3P0鏈接池完成基本數據庫的操做。
使用DBUtils完成CRUD的操做。
 
數據庫鏈接池的解決方案是:
當應用程序啓動時,系統主動創建足夠的數據庫鏈接,並將這些鏈接組成一個鏈接池。每次應用程序請求數據庫鏈接時,無須從新打開鏈接,而是從鏈接池中取出已有的鏈接使用,使用完後再也不關閉數據庫鏈接,而是直接將鏈接歸還給鏈接池。經過使用鏈接池,將大大提升程序的運行效率。
 
數據庫鏈接池是Connection 對象的工程。數據庫鏈接池的經常使用參數以下。
a、數據庫的初始鏈接數
b、鏈接池的最大鏈接數
c、鏈接池的最小鏈接數
d、鏈接池每次增長的容量
 
公共接口:javax.sql.DataSource。
常見的鏈接池:DBCP 、 C3P0 (主要)
 
自定義鏈接池代碼實現改進(加強close方法):
    自定義鏈接池中存在的嚴重問題,用戶調用getConnection()得到鏈接後,必須使用release()方法進行鏈接的歸還,若是用戶調用conn.close()將鏈接真正的釋放,鏈接池中將出現無鏈接能夠。
 
方法加強的辦法:
a、繼承,子類繼承父類,將父類的方法進行復寫,從而進行加強。
    使用前提:必須有父類,且存在繼承關係。
b、裝飾者設計模式,此設計模式專門用於加強方法。
    使用前提:必須有接口
    缺點:須要將接口的全部方法都實現
c、動態代理:在運行時動態的建立代理類,完成加強操做。與裝飾者類似
    使用前提:必須有接口
    難點:須要反射技術
d、字節碼加強,運行時建立目標類子類,從而進行加強
    常見第三方框架:cglib 、javassist等。
 
鏈接池釋放資源問題(WEB_10視頻05自定義鏈接池代碼實現改進(加強close方法)):
使用 c3p0 的話,也是 java.sql.Connection,只要是 JDBC 都是這個接口的對象!
 
使用完後必須 con.close() 掉,使用鏈接池的話,執行 con.close 並不會關閉與數據庫的 TCP 鏈接,而是將鏈接還回到池中去,若是不 close 掉的話,這個鏈接將會一直被佔用,直接鏈接池中的鏈接耗盡爲止。
 
至因而如何作到 con.close 並非真正意義上的關閉鏈接?而是直接將鏈接還回到池中去?
 
通常有兩種方式:
 
一:使用裝飾器模式,在裝飾器構造中傳入一個真正的 Connection,這個裝飾器實現 Connection,使用構造 傳入 Connection 委託重寫全部方法,並改寫 close 方法:
 
Java code
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ConnectionDecorator implements Connection {
 
    private Connection con = null;
     
    public ConnectionDecorator(Connection con) {
        this.con = con;
    }
     
    public void close() throws SQLException {
        // 重寫!
    }
 
    public void commit() throws SQLException {
        this.con.commit();
    }
 
    public Statement createStatement() throws SQLException {        
        return this.con.createStatement();
    }
 
    public Statement createStatement(int resultSetType, int resultSetConcurrency)
            throws SQLException {
        return this.con.createStatement(resultSetType, resultSetConcurrency);
    }
 
    ......
}
 
 
 
而後通過鏈接池控制的 Connection 對象都使用該裝飾器進行包裝
 
二:動態代理:
 
使用動態代理從新實現 close 方法,每一個得到 Connection 是一個代理後的對象。
 
 
一個完善的鏈接池,其架構設計很是複雜,Connection#close 問題就是鏈接池諸多設計難點當中的一個。
 
 
總結:
關於學習MySql 以及JDBC方面的總結!
1、MySql  
MySQL基本命令
SQL(全稱)語句基礎:DML 、 DDL 、 DCL 、 DQL
數據庫約束
查詢(單表、多表   左右鏈接等)
truncate  和  delete比較?
等等等
 
2、JDBC編程步驟
一、加載驅動     
c3p0-config.xml
db.properties     
二、獲取鏈接    
鏈接池概念
步驟   J3P0(XML)
三、DBUtils   完成CRUD (增刪改查)
封裝JDBC操做,簡化JDBC操做
JavaBean組件(封裝數據)   包:com.scalpet.domain
四、使用完鏈接池後:釋放資源
得出結論,DBUtils在建立QueryRunner時傳入dataSource對象每次在執行完以後都會自動關閉Connection鏈接對象~因此不再用擔憂沒有關閉對象而致使的問題了~若是沒有傳入dataSource的話 ·····須要手動關閉
 
3、練習
a、創建工程---java project
b、導入JDBC鏈接的jar包---jar包都添加在新文件夾lib下面
c、導入c3p0jar包
d、編寫c3p0-config.xml文件
e、編寫C3P0工具類---其核心工具類ComboPooledDataSource(命名配置、默認配置)---工具類都放在新建包com.scalpel.utils包下
f、編寫JavaBean組件User----組件在新建包com.scalpel.domain包下
g、導入DBUtils的jar包
h、編寫DBUtils的測試java類
 
代碼實現:
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
 
  <default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
       <property name="jdbcUrl">jdbc:mysql:///web</property>
       <property name="user">root</property>
       <property name="password">12345678</property>
       <property name="initialPoolSize">5</property>
       <property name="maxPoolSize">20</property>
  </default-config>
 
  <named-config name="scalpel">
    <property name="driverClass">com.mysql.jdbc.Driver</property>
       <property name="jdbcUrl">jdbc:mysql:///web</property>
       <property name="user">root</property>
       <property name="password">12345678</property>
  </named-config>
 
 
</c3p0-config>
 
C3P0Utils工具類:
package com.scalpel.jdbc.utils;
 
import java.sql.Connection;
import java.sql.SQLException;
 
import javax.sql.DataSource;
 
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
public class C3P0Utils {
       
       //使用命名配置
       private static ComboPooledDataSource dataSource = new ComboPooledDataSource("scalpel");
       
       /*
        * 得到數據源(鏈接池)
        */
       public static DataSource getDataSource()
       {
             return dataSource;
       }
       
       /*
        * 得到鏈接
        */
       public static Connection getConnection()
       {
             try {
                    return dataSource.getConnection();
             } catch (SQLException e) {
                    throw new RuntimeException();
             }
       }
}
 
userbean組件類:
package com.scalpel.domain;
 
public class User {
       
       private  int id;
       private  String name;
       private  String password;
       public int getId() {
             return id;
       }
       public void setId(int id) {
             this.id = id;
       }
       public String getName() {
             return name;
       }
       public void setName(String name) {
             this.name = name;
       }
       public String getPassword() {
             return password;
       }
       public void setPassword(String password) {
             this.password = password;
       }
       
       
}
 
鏈接測試類:
package com.scalpel.jdbc.link;
 
import java.sql.SQLException;
import java.util.List;
 
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
 
import com.scalpel.domain.User;
import com.scalpel.jdbc.utils.C3P0Utils;
 
public class LinkJDBC {
 
       /*
        * 添加用戶
        */
       @Test
       public void AddUser() {
             try {
                    // 1.鏈接數據源鏈接池
                    QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
                    // 2.編寫sql語句
                    String sql = "insert into user values( ?, ?, null )";
                    // 3.添加params參數
                    Object[] params = { "ctxixi", "123" };
                    // 4.執行sql語句
                    int rows = qr.update(sql, params);
                    // 5.判斷是否執行成功
                    if (rows > 0) {
                           System.out.println("添加成功");
                    } else {
                           System.out.println("添加失敗");
                    }
             } catch (SQLException e) {
                    e.printStackTrace();
             }
       }
 
       /*
        * 查詢用戶,使用BeanListHandler
        */
       @Test
       public void QueryAllUserInf()
       {
             try {
                    QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
                    String sql = "select * from user";
                    List<User> queryUser = qr.query(sql, new BeanListHandler<User>(User.class));
                    for (User user : queryUser)
                    {
                           System.out.println(user.getId() +"、" + user.getName() + " : " + user.getPassword());                      
                    }                   
             } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             }
       }
 
}
相關文章
相關標籤/搜索