JDBC和數據庫連接池


  JDBC是一種用於執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。

● JDBC

● C3P0

● DRUID


 

一.JDBC

1.基本使用

使用 JDBC 操作MySQL數據庫時,可以將步驟分為以下7步:

// 1.注冊驅動(將mysql的驅動類加載到內存中)
DriverManager.registerDriver(new Driver());
// 2.獲取連接
String url = "jdbc:mysql://localhost:3306/db";
String username = "root";
String password = "root";
Connection con = DriverManager.getConnection(url, username, password);
// 3.編寫sql
String sql = " ... ";
// 4.獲取語句的執行器
Statement statement = con.createStatement();
// 5.執行sql並返回結果集
ResultSet rs = statement.excuteQuery(sql);
// 6.處理結果集
while(rs.next()){ ... }
// 7.釋放資源
rs.close();
statement.close();
con.close();

2.PreparedStatement:預編譯對象 

為防止 SQL 注入,我們先將sql 傳給數據庫,將sql語句事先編譯好,使用時直接賦真實值,執行sql即可。

// 使用 ? 占位
String sql = "select * from stu where id= ? "
// 創建預編譯對象
PreparedStatement pst = con.prepareStatement(sql);
// 設置具體的參數 (第幾個 ?, 具體值)
pst.set(1, 2);
// 執行sql
ResultSet rs = pst.executeQuery();
int i = pst.executeUpdate();

3.封裝優化

由於Driver類的源碼當中有注冊驅動的靜態代碼塊,因此我們可以不用自己再去注冊(類加載后就完成了注冊),同時為了避免硬編碼和代碼冗余我們將其優化,封裝成簡單工具類。

1.編寫配置文件 :Jdbc.properties

# 數據庫驅動配置
# Driver類的全限定類名(加載即完成注冊)
jdbc.driver=com.mysql.jdbc.Driver
#        協議  協議   地址       端口  數據庫
jdbc.url=jdbc:mysql://localhost:3306/db
# 用戶名
jdbc.username=root
# 密碼
jdbc.password=root

2.編寫工具類 :JdbcUtils

public class JdbcUtils {
    //聲明配置信息
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    private static Connection con;
    //靜態代碼塊,類加載時解析配置信息
    static {
        try {
            InputStreamReader is = new InputStreamReader
                (JdbcUtils.class.getResourceAsStream("/jdbc.properties"));
            Properties properties = new Properties();
            properties.load(is);
            driver = properties.getProperty("jdbc.driver").trim();
            url = properties.getProperty("jdbc.url").trim();
            username = properties.getProperty("jdbc.username").trim();  
            password = properties.getProperty("jdbc.password").trim();
            //加載驅動獲取連接
            Class.forName(driver);
            con =  DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 獲取數據庫連接(如果連接關閉則重新創建)
    public static Connection getConnection() {
        try {
            if (con.isClosed()) {
                con =  DriverManager.getConnection(
                    url,username,password);
                return con;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
        return con;
    }
    // 關閉資源(有結果集)
    public static void close(ResultSet rs, Statement s, 
                             Connection con) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (s != null) {
            try {
                s.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    // 關閉資源(無結果集)
    public static void close(Statement s, Connection con) {
        close(null, s, con);
    }
}

3.注意事項

// 需要注意的是
// 1.將jdbc.properties放到src文件下

// 2.解析配置文件時除上述寫法還可以使用如下方式(此法針對src下的properties文件):
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
driver = bundle.getString("jdbc.driver").trim();
url = bundle.getString("jdbc.url").trim();
username = bundle.getString("jdbc.username").trim();
password = bundle.getString("jdbc.password").trim();

在使用上述方法連接並操作數據庫時,若沒有按照上面的代碼對連接的狀態進行檢查那么肯定會遇到這樣一個異常:No operations allowed after connection closed. 因為我們只創建了一個連接,當完成一個操作后將其關閉,那么下一次操作獲得的連接就是已經關閉了的連接,因此會發生此異常!上述代碼中對連接進行了狀態的判斷,比較麻煩。而數據庫連接池正是維護着幾個連接供我們使用,使用后將其歸還至連接池(並不是真的關閉)。

二.C3P0連接池

C3P0是開源的連接池,Hibernate框架默認使用的就是C3P0連接池。使用配置文件創建連接池時注意文件名稱“ c3p0-config.xml"不能更改(放在src下)。

1.創建配置文件:c3p0-config.xml

<c3p0-config>
  <!-- 使用默認的配置讀取連接池對象 -->
  <default-config>
      <!--  連接參數 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <!-- 連接池參數 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">3000</property>
  </default-config>
<!--  指定名稱的配置信息 -->
  <named-config name="myc3p0"> 
    <!--  連接參數 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
    <property name="user">root</property>
    <property name="password">root</property>  
    <!-- 連接池參數 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>

2.獲取連接池對象

// 關鍵代碼
// 使用默認配置獲取連接池對象
ComboPooledDataSource comboPooledDataSource =
    new ComboPooledDataSource();
// 使用指定的配置  (配置名) 獲取連接池對象
ComboPooledDataSource comboPooledDataSource = 
    new ComboPooledDataSource("myc3p0");

三.DRUID(德魯伊)連接池

DRUID是阿里巴巴開發的目前最好的數據庫連接池。 com.alibaba.druid.pool.DruidDataSourceFactory 類創建連接池的方法:

1.創建配置文件:mydruid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
minIdle=3  # 最小連接池數量

2.獲取連接池對象

Properties prop = new Properties();
InputStream is = DruidDemo.class.getClassLoader().
    getResourceAsStream("mydruid.properties");
prop.load(is);
//druid工廠根據配置文件創建druid連接池對象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

四.DRUID工具類封裝

1.配置文件(參上)

2.關鍵代碼

private static DataSource dataSource;
 static{
     try {
         // 解析druid的配置文件
         Properties prop = new Properties();
         InputStream is = JDBCUtil.class.getClassLoader().
             getResourceAsStream("druid.properties");
         prop.load(is);
         // druid工廠使用配置文件創建druid連接池對象
         dataSource = DruidDataSourceFactory.createDataSource(prop);
     } catch (Exception e) {
         e.printStackTrace();
     }
 }
 //獲取druid連接池
 public static DataSource getDataSource(){
     return dataSource;
 }
 //獲取druid連接池中的連接
 public static Connection getConnection() throws SQLException {
     return dataSource.getConnection();
 }
 //釋放資源(歸還連接)
 public static void close(ResultSet rs, Statement st,Connection conn) {
     if(rs!=null){
         try {
             rs.close();
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
     if(st!=null){
         try {
             st.close();
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
     if(conn!=null){
         try {
             conn.close();
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
 }
 public static void close(Statement st,Connection conn) {
     close(null,st,conn);
    }

Tips:

// 將properties文件放到src下時
JdbcUtils.class.getResourceAsStream("/jdbc.properties")
//兩種方式的參數不一樣
JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties")

 

 

關注微信公眾號,隨時隨地學習


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM