第77節:Java中的事務和資料庫連線池和DBUtiles

達叔小生發表於2019-01-27

標題圖

第77節:Java中的事務和資料庫連線池和DBUtiles

前言

看哭你,字數:8803,承蒙關照,謝謝朋友點贊!

字數8803

事務

Transaction事務,什麼是事務,事務是包含一組操作,這組操作裡面包含許多個單一的邏輯,只要有一個邏輯沒有執行成功就算失敗,導致回滾就是指所有的資料都會回到最初的狀態.

有事務,是為了保證邏輯一定要成功,如銀行轉賬.

回顧一下

什麼是jsp,jsp的三大指令.

page: 定義當前頁面的資訊
include: 包含其他頁面
taglib: 引入標籤庫

三大動作標籤:

<jsp:forward page="">:跳轉
<jsp:param name="" value="">:跳轉到具體頁面或是某個頁面被包含的時候,可以指定引數
<jsp:include page="">:包含

九大內建物件:

// 四個作用域
pageContext 當前頁
request 請求 一次請求 響應後就不行了
session 會話 一次會話
application 都可以 整個專案,直到關閉伺服器

// 5
response
out
exception
config -> ServletConfig
page -> this 翻譯成java檔案的類物件

EL

${ 表示式 };

取值

<% User user = new User(); %>
${user.ame}
從四個作用域裡面找 
pageContext -> request -> session -> application
<%
 User user = new User();
 pageContext.setAttribute("user",user);
%>
${sessionScope.user.name}強制用session找

EL的11個隱式物件:

pageContext
// 作用域
pageScope
requestScope
sessionScope
applicationScope

頭相關
header
headerValues
引數
param
paramValues
cookie
initparam

JSTL

導包哦,引入標籤庫是1.1的:

<c:set>: 儲存到作用域
<c:set var="" value="" scope="">
<c: if>: 用來判斷
<c:forEach items="" var="">:用於遍歷

資料庫

新增兩條資料

資料庫命令列:

命令列

命令列

關閉自動提交.

關閉了提交,再減100:

命令列

會到資料庫檢視:

重新整理了

值沒改變!

輸入提交後

重新整理改變

開啟事務

新增改變程式碼:

先看錶

package com.dashucoding.test;

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

import org.junit.Test;

import com.dashucoding.util.JDBCUtil;
 
public class TestDemo { 
    
    @Test
    public void testTransaction() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            //查詢資料
            /*String sql = "select * from account";
            ps = conn.prepareStatement(sql);*/
            
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            
            // 扣錢
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            
            /*ps.setInt(1, -100);
            ps.setInt(2, 1);
            ps.executeUpdate();*/
            
            // 查詢資料 
            /*rs = ps.executeQuery();
            while(rs.next()) {
                System.out.println(rs.getString("name")+"=="+rs.getInt("money"));
            }*/
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps, rs);
        }
    }
}
package com.dashucoding.util;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
    
    static String driverClass = null;
    static String url = null;
    static String name = null;
    static String password= null;
    
    static{
        try {
            //1. 建立一個屬性配置物件
            Properties properties = new Properties();
            InputStream is = new FileInputStream("jdbc.properties");
            
            
            //使用類載入器,去讀取src底下的資原始檔。 後面在servlet
//          InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //匯入輸入流。
            properties.load(is);
            
            //讀取屬性
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            name = properties.getProperty("name");
            password = properties.getProperty("password");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 獲取連線物件
     * @return
     */
    public static Connection getConn(){
        Connection conn = null;
        try {
            Class.forName(driverClass);
            //靜態程式碼塊 ---> 類載入了,就執行。 java.sql.DriverManager.registerDriver(new Driver());
            //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
            //2. 建立連線 引數一: 協議 + 訪問的資料庫 , 引數二: 使用者名稱 , 引數三: 密碼。
            conn = DriverManager.getConnection(url, name, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    
    /**
     * 釋放資源
     * @param conn
     * @param st
     * @param rs
     */
    public static void release(Connection conn , Statement st , ResultSet rs){
        closeRs(rs);
        closeSt(st);
        closeConn(conn);
    }
    public static void release(Connection conn , Statement st){
        closeSt(st);
        closeConn(conn);
    }

    
    private static void closeRs(ResultSet rs){
        try {
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            rs = null;
        }
    }
    
    private static void closeSt(Statement st){
        try {
            if(st != null){
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            st = null;
        }
    }
    
    private static void closeConn(Connection conn){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            conn = null;
        }
    }
}

重新整理後

事務只針對連線.

package com.dashucoding.test;

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

import org.junit.Test;

import com.dashucoding.util.JDBCUtil;
 
public class TestDemo { 
    
    @Test
    public void test02(){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            
            //扣錢, 扣ID為1 的100塊錢
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            
            
            //int a = 10 /0 ;
            String s = null;
            s.length();
            
            //加錢, 給ID為2 加100塊錢
            ps.setInt(1, -100);
            ps.setInt(2, 2);
            ps.executeUpdate();
            
            
        } catch (SQLException e) {
            
            e.printStackTrace();
            
        }finally {
            JDBCUtil.release(conn, ps, rs);
        }
    }
    
    @Test
    public void testTransaction() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            
            // 連線
            conn.setAutoCommit(false);
            
            //查詢資料
            /*String sql = "select * from account";
            ps = conn.prepareStatement(sql);*/
            
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            
            // 扣錢
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            
            int a = 10 /0 ;
            
            ps.setInt(1, -100);
            ps.setInt(2, 2);
            ps.executeUpdate();
            
            // 提交事務
            conn.commit();
            
            // 查詢資料 
            /*rs = ps.executeQuery();
            while(rs.next()) {
                System.out.println(rs.getString("name")+"=="+rs.getInt("money"));
            }*/
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            // 回滾事務
            try {
                conn.rollback();
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps, rs);
        }
    }
}

事務

conn.setAutoCommit(false)來關閉自動提交的設定
conn.commit(); 提交事務
conn.rollback(); 回滾事務

記住:
什麼是事務,事務有什麼用處,事務怎麼用.

事務的特點:

  1. 原子性: 指的是事務中包含的邏輯,不可以分割(事務中邏輯不可分)
  2. 一致性: 事務執行前和執行後,保持資料的完整性一致(執行前後,資料保持一致)
  3. 隔離性: 事務在執行期間不受到其他事務的影響(隔離不受影響)
  4. 永續性: 事務執行結束,提交或回滾,資料都應該持久化到資料中(資料持久化在資料中)

安全問題

  1. 讀問題
    髒讀,不可重複讀,幻讀
  2. 寫問題
    丟失更新,解決丟失更新的方法,一悲觀鎖和樂觀鎖

隔離級別

Read Uncommitted 讀未提交
Read Committed 讀已提交
Repeatable Read 重複讀
Serializable 可序列化

隔離級別

髒讀:

命令列

效果

一條連線:
效果

另一條連線:
效果

use bank;
start transaction;
select * from account;
select * from account;
use bank;
start transaction;
update account set money = money + 300 where id = 1;
commit;

讀未提交

效果

例子

命令

這裡查詢,然後再看看資料庫中的表:

重新整理後

命令提交:

命令提交

查詢資料

不可重複讀的問題

效果

Repeatable Read重複讀

命令

命令

表

命令

可串化

命令

命令

讀未提交,引發髒讀,讀已提交解決髒讀,引發不可重複讀, 可重複讀解決髒讀解決了髒讀,不可重複讀,

asss

小結

讀:
髒讀 不可重讀讀 幻讀

髒讀:
一個事務讀到另外一個事務還未提交的資料

不可重複讀:
一個事務讀到另外一個事務提交的資料,導致前後兩次查詢結果不一致

幻讀:
一個事務讀到了另外一個事務已提交的插入的資料,導致多次查詢結果不一致.

讀未提交,
會導致丟失更新

讀已提交,
能夠遮蔽 髒讀的現象,但是引發不可重複讀

事務的安全隱患髒讀

隔離級別:

read uncommitted 讀未提交
read committed 讀已提交
repeatable read 重複讀
serializable 可串化

mysql預設的是重複讀.

設定A視窗的隔離級別為 讀未提交

a

兩個視窗都分別開啟事務

髒讀

提交後

讀未提交是一個事務可以讀取到另一個事務還沒有提交的資料,會引發髒讀現象,讀取到的是資料庫記憶體中的資料,並不是真正的磁碟上的資料.

還未提交時,資料庫記憶體中的資料是不會改變的,只有到commit提交後,資料庫中的資料才會提交,從而讀取真正在磁碟上的資料.

Read Committed讀已提交

命令

命令

在a發生了變化,遮蔽了髒讀,引發不可重複讀,讀已提交.讀已提交,在a視窗設定的是讀已提交,兩邊開啟事務.在b視窗更新操作.

在a視窗查詢結果不一致,一次是在b視窗提交事務之前,一次的提交之後.

前後

引發了不可重複讀

不可重複讀,一個事務讀取到了另一個事務提交的資料,導致前後兩次查詢結果不一致.

會造成問題是前後讀取到的結果不一樣,發生了不可重複讀,就是不可以 重複讀取, 就是不能執行多次讀取, 否則會導致結果不一致, 這下好了, 讀取已提交導致了 重複讀取, 結果還不一致, 就出現了叫 不可重複讀 現象.

安全隱患_可重複讀

Repeatable Read重複讀, 重複讀就是mysql預設的隔離級別,可以讓食物在自己的會話中重複讀取資料,並且不會出現結果不一致的現象, 就算其他事務提交了, 也還是會在視窗中出現以前的資料, 這就是可重複讀了.

重複讀, 就是讓它可以重複查詢, 結果還是和以前一樣的效果出現.

設定重複讀

重複讀

重複讀

安全隱患 _可序列化

幻讀:什麼是幻讀呢?
就是一個事務讀到另一個事務已提交的插入的資料,會導致多次查詢結果不一致.就是幻讀,是不是幻讀理解為我幻想了, 事務已提交的插入資料, 導致幻想了,(幻讀) 導致每次查詢結果不一樣.

事務已提交,多次查詢結果不一致.

幻讀->Serializable可序列化

該事務的級別是最高的事務級別,我是可序列化,是最高的.可以解決如下小弟的問題,如髒讀,不可重複讀,幻讀,因為我是可序列化,是大佬,但作為大佬,還是會有缺點的.

命令列

命令

命令

是的,a提交才動.現在我們讓b先開啟事務.

命令

命令列

提交了

可序列化, 誰先開啟事務,就誰有權利,這個隔離級別,先開啟就有權利讓別人等著,等先開啟事務的那個傢伙,提交或者回滾後,才能進行,這種級別是用得比較少的,因為容易導致效能上效率低下.

隔離級別有四個哦

  1. 讀未提交
  2. 讀已提交
  3. 可重複讀
  4. 可序列化

如果按照效率劃分,從高到低,排個名次如下:

  1. 讀未提交 -> 髒讀
  2. 讀已提交 -> 不可重複讀
  3. 可重複讀 -> 解決重複讀
  4. 可序列化 -> 以上都是我小弟來著

按照攔截程度來劃分,從高到底,排名如下:

  1. 可序列化 -> 我是大哥
  2. 可重複讀 -> 我是二哥
  3. 讀已提交 -> 我是三弟
  4. 讀未提交 -> 我是小弟

事務_隔離級別小結

// 使用事務
conn.setAutoCommit(false);
// 提交
conn.commit();
// 回滾
conn.rollback();

事務只是針對連線物件.事務是會自動提交的.

安全隱患和隔離級別

安全隱患: 讀的安全隱患和寫的安全隱患

讀:
髒讀,讀到未提交的資料,一個事務讀到了另一個事務未提交的資料;
不可重複讀,就是一個事務讀到了另一個事務已經提交的資料,導致前後兩次查詢的結果不一致;
幻讀,就是一個事務讀到了另一個事務新增的資料,導致前後查詢結果不一致.

寫: 丟失更新…

隔離級別

讀未提交,導致髒讀
讀已提交,解決髒讀,導致不可重複讀
可重複讀,解決髒讀和不可重複讀,導致幻讀
可序列化,解決髒讀,不可重複讀,幻讀

預設的mysql是可重複讀,oracle預設是讀已提交

寫的問題_丟失更新

丟失更新

  1. 樂觀鎖
  2. 悲觀鎖

安全問題包含 讀的問題和寫的問題

事務的特性是什麼?
原子性,一致性,隔離性,永續性

寫的問題_丟失更新

效果

效果

b視窗沒有提交.等待提交中:

案例控制皮膚,我的a:

a的

b的

哭了,這是設定預設的重複讀啊!

丟失更新的問題

聽說丟失更新

a事務和b事務同時查詢一個表,a開始修改並提交name欄位的名字,然後b事務開始修改該行的money的欄位,如果b事務提交,那麼之前a事務修改的名字沒有了,變回去了哦,當然b事務回滾,也同樣導致a事務更新沒有了哦.回滾也會把之前b事務的最初的資料還原.

這裡的情況處理序列化級別外,就是可序列化級別大佬哦!

解決丟失更新的方法

  1. 悲觀鎖
  2. 樂觀鎖
select * from account;

悲觀鎖的態度,它是悲觀的態度,它是一定會丟失更新,它的想法是我一定會出錯.

而樂觀鎖,它的態度是我一定不會丟失更新.

悲觀鎖

資料庫的鎖機制,排他鎖

select * from account for update;

命令

命令列

丟失更新的問題

不考慮隔離性,產生寫入資料導致的問題為丟失更新的問題,兩個事務同時對某一條記錄做修改,然後會導致丟失更新的問題.

a,b兩個事務同時獲取一條資料,同時做了修改,a事務修改後,提交了事務,b事務修改後,不管是提交還是回滾,都會對資料發生影響.

悲觀鎖記住用了這句:

select * from account for update;
for update;
資料庫鎖機制,排他鎖

樂觀鎖

a事務先提交,資料庫版本version變為1,b事務在提交的時候,比對資料庫version和自己的version是不一樣的,不允許提交,要先更新.

a提交的時候版本變為1,b提交的時候,發現版本不一致就無法提交,要進行更新後提交.

資料庫連線池

什麼是連線池,連線池的作用是什麼,自定義連線池,開源的連線池?

那麼什麼是資料庫連線池?

資料庫連線池是Java程式和資料連線的中介媒介,以前一個Java程式對應一個連線,然後就可以連線到資料了,可以一旦多了呢?

就有人發明了資料庫連線池,可以一下連線多個,但是是有限制的,一旦多了,就會擴容,額外增加3到5個,不會增幅太大,也有最大值的限制.

資料庫的連線物件 建立工作 比較消耗效能
一開始在記憶體中會開闢一塊空間, 用於是 這個資料庫連線池的空間, 可以在池子裡放置很多個連線物件, 資料庫連線池裡有很多個連線物件, 後面需要連線的話會直接從池子裡面去, 就不用自己去建立連線了, 因為資料庫的連線物件建立工作是比較耗時的, 使用完, 資料庫連線池中的 連線物件 ,是要進行歸還的, 確保連線物件可以迴圈連線使用.

建立資料庫的連線池

// 簡單使用資料庫連線池
package com.dashucoding.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

public class TestPool {
    
    @Test
    public void testPool() {
        Connection conn = null;
        PreparedStatement ps = null;
        MyDataSource dataSource = new MyDataSource();
        try {
    
            conn = dataSource.getConnection();
            
            String sql = "insert into account values (null, `xilali`, 10)";
            ps = conn.prepareStatement(sql);
            ps.executeUpdate();
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                ps.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 歸還連線
            dataSource.addBack(conn);
        }
    }
}

結構

自定義資料庫連線池

List <Connection> list = new ArrayList<Connection>();

解決自定義資料庫連線池問題

因為多了一個addBack方法,要記住這個方法,且不能用面向介面程式設計.修改close方法,改成不是關閉而是歸還連線物件.

public class MyDataSource implements DataSource {
 // 建立連線池
List<Connection> list = new ArrayList<Connection>();
 public MyDataSource(){
  for(int i = 0; i < 10; i++){
   Connection conn = JDBCUtil.getConn();
   list.add(conn);
  }
 }
 @Override
 public Connection getConnection() throws SQLException {
   if(list.size() == 0){
     for(int i=0; i<5; i++) {
      Connection conn = JDBCUtil.getConn();
       list.add(conn);
     }
    }
    Connection conn = list.remove(0);
     return conn;
  }
  // 用完後歸還 
  public void addBack(Connection conn){
    list.add(conn);
  }
}
public class TestPool{
 @Test
  public void testPool(){
   Connection conn = null;
   PreparedStatement ps = null;
   MyDataSource dataSource = new MyDataSource();
  try {
   conn = dataSource.getConnection();
   String sql = "insert into account values(null, `dashu`, 10)";
   ps = conn.prepareStatement(sql);
   ps.executeUpdate();
 
   }catch(SQLException e){
    e.printStackTrace();
   }finally{
    try{
    ps.close();
    }catch(SQLException e){
     e.printStackTrace();
    }
    // 歸還連線
    dataSource.addBack(conn);
   }
  }
}

如何擴充套件方法

裝飾者模式

package com.dashucoding.test;

public interface Waiter {
    void service();
}
package com.dashucoding.test;

public class Waitress implements Waiter {
    @Override
    public void service() {
        System.out.println("在服務...");
    }
}
package com.dashucoding.test;

public class MainTest {
    public static void main(String[] args) {
        Waiter waiter = new Waitress();
        waiter.service();
    }
}

裝飾者模式:

package com.dashucoding.test;

public class WaitressWrap implements Waiter {
    
    Waiter watier = null;
    public WaitressWrap(Waiter watier) {
        this.watier = watier;
    }

    @Override
    public void service() {
        // TODO Auto-generated method stub
        System.out.println("微笑");
        watier.service();
    }
    
}
package com.dashucoding.test;

public class MainTest {
    public static void main(String[] args) {
        /*Waiter waiter = new Waitress();
        waiter.service();*/
        WaitressWrap waitressWrap = new WaitressWrap(new Waitress());
        waitressWrap.service();
    }
}

分析

Waiter -> service()

Waitress -> service()

WaitressWrap -> service()

Waiter waiter;
public Waitress Wrap(Waiter waiter){
 this.waiter = watier;
}
void service(){
 syso
 waiter.service();
}

裝飾者模式

結構

程式碼

package com.dashucoding.util;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;
// 這是一個資料庫連線池
// 一開始 先往連線池放入10個連線
public class MyDataSource implements DataSource{
    
    // 建立連線池
    List<Connection> list = new ArrayList<Connection>();
    public MyDataSource() {
        // 10個連線
        for(int i = 0; i < 10; i++) {
            Connection conn = JDBCUtil.getConn();
            list.add(conn);
        }
    }
    
    // 該連線池對外公佈的獲取連線的方法
    @Override
    public Connection getConnection() throws SQLException {
        // 來拿連線的時候,看看,池子裡面有沒有
        if(list.size() == 0) {
            for(int i = 0; i < 5; i++) {
                Connection  conn = JDBCUtil.getConn();
                list.add(conn);
            }
        }
        
        // TODO Auto-generated method stub
        // 那一個 給連線 如果有10個,0,1,2,3,->10 這樣給
        // 確保給
        // 移除就給了嘛
        // remove(0) -> 移除第一個
        Connection conn = list.remove(0);
        // 把物件丟擲去的時候,對這個物件進行包裝
        
        Connection connection = new ConnectionWrap(conn,list);
        
        return connection;
    }
    
    // 用完後記得歸還
    public void addBack(Connection conn) {
        list.add(conn);
    }
    
    
    
    
    
    
    
    @Override
    public PrintWriter getLogWriter() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getLoginTimeout() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter arg0) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setLoginTimeout(int arg0) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public boolean isWrapperFor(Class<?> arg0) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> arg0) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }



    @Override
    public Connection getConnection(String arg0, String arg1) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

}

程式碼

package com.dashucoding.util;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class ConnectionWrap implements Connection{
    
    Connection connection = null;
    
    List<Connection> list;
    public ConnectionWrap(Connection connection,List<Connection> list) {
        super();
        this.connection = connection;
        this.list = list;
    }

    @Override
    public void close() throws SQLException {
        // TODO Auto-generated method stub
        //connection.close();
        System.out.println("有人歸還連線物件了,歸還之前"+list.size());
        list.add(connection);
        System.out.println("有人歸還連線物件了,歸還之後"+list.size());
    }
    
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return connection.prepareStatement(sql);
    }
    
    
    
    
    
    
    

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void abort(Executor executor) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void clearWarnings() throws SQLException {
        // TODO Auto-generated method stub
        
    }



    @Override
    public void commit() throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Clob createClob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Statement createStatement() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public String getCatalog() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getHoldability() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getSchema() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isClosed() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isReadOnly() throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
            int resultSetHoldability) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }



    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
            throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
            int resultSetHoldability) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void rollback() throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setSchema(String schema) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        // TODO Auto-generated method stub
        
    }
    
}

效果

程式碼

資料庫連線池_DBCP

DBCP開源連線池
C3P0,什麼是C3P0,怎麼用

DBCP為資料庫連線池,是java資料庫連線池的一種是Apache開發的,通過資料庫連線池可以讓程式自動管理資料庫的連線.

DataBase Connection Pool資料庫連線池

C3P0也是一種開源的連線池,實現了資料庫和JNDI繫結,使用它的開源專案:

Spring, Hibernate

怎麼用DBCP

  1. 匯入jar包
commons-dbcp.jar
commons-pool.jar
// 不使用配置檔案
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://loclhost/users");
dataSource.setUsername("root");
dataSource.setPassword("root");

conn = dataSource.getConnection();
String sql = "select * from user";
pstmt = conn.prepareStatement(sql);

DBCP連線資料庫使用

package com.dashucoding.dbcp;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;

import com.dashucoding.util.JDBCUtil;

// 這個連線池要連線資料庫, 賬號,密碼
public class DBCPDemo {
    // ctrl + 2 f
    private Connection conn;
    private PreparedStatement ps;

    @Test
    public void testDBCP01(){
        // 資料庫的連線池, 作用建立和連線
        
        try {
            // 構建資料來源物件
            BasicDataSource dataSource = new BasicDataSource();
            // 連線什麼資料庫,使用者名稱和密碼
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost/bank");
            dataSource.setUsername("你的賬戶");
            dataSource.setPassword("你的密碼");
            
            // 得到連線物件
            conn = dataSource.getConnection();
            
            String sql = "insert into account values(null, ?, ?)";
            
            ps = conn.prepareStatement(sql);
            
            ps.setString(1, "dashucoding");
            ps.setInt(2, 10000);
            
            ps.executeUpdate();
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, ps);
        }
        
    }
}

以上是不使用配置檔案的情況.

DBCP使用配置檔案方式

結構

效果

package com.dashucoding.dbcp;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;

import com.dashucoding.util.JDBCUtil;

public class DBCPDemo02 {

    @Test
    public void testDBCP02() {
        /*BasicDataSource dataSource = new BasicDataSource();
        dataSource.setConnectionProperties("dbcpconfig.properties");*/

        
        Connection conn = null;
        PreparedStatement ps = null;

        // 資料庫的連線池, 作用建立和連線
        try {
            BasicDataSourceFactory factory = new BasicDataSourceFactory();
            Properties properties = new Properties();
            InputStream is = new FileInputStream("src//dbcpconfig.properties");
            properties.load(is);
            DataSource dataSource = factory.createDataSource(properties);

            // 得到連線物件
            conn = dataSource.getConnection();

            String sql = "insert into account values(null, ?, ?)";

            ps = conn.prepareStatement(sql);

            ps.setString(1, "liuliuliu");
            ps.setInt(2, 10000);

            ps.executeUpdate();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps);
        }

    }

}

資料庫連線池_C3P0

不使用配置方式

拷貝jar c3p0...jar
 Just put the jar file [lib/c3p0-0.9.1.2.jar] in your application`s effective CLASSPATH
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver            
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("dbuser");                                  
cpds.setPassword("dbpassword");   

結構

package com.dashucoding.c3p0;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;

import com.dashucoding.util.JDBCUtil;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Demo {
    @Test
    public void testC3P0() {

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            // 建立dataSource
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            
            dataSource.setDriverClass("com.mysql.jdbc.Driver");        
            dataSource.setJdbcUrl( "jdbc:mysql://localhost/bank" );
            dataSource.setUser("root");                                  
            dataSource.setPassword("admin");  
            

            // 得到連線物件
            conn = dataSource.getConnection();

            String sql = "insert into account values(null, ?, ?)";

            ps = conn.prepareStatement(sql);

            ps.setString(1, "aaa");
            ps.setInt(2, 10000);

            ps.executeUpdate();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps);
        }

    }

}

C3P0使用配置檔案的方式

圖片

圖片

效果

c3p0-config.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
  <default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost/bank</property>
    <property name="user">你的賬戶</property>
    <property name="password">你的密碼</property>
    
    
    <property name="initialPoolSize">10</property>
    <property name="maxIdleTime">30</property>
    <property name="maxPoolSize">100</property>
    <property name="minPoolSize">10</property>
    <property name="maxStatements">200</property>

  </default-config>
  
</c3p0-config>

效果

package com.dashucoding.c3p0;

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.junit.Test;

import com.dashucoding.util.JDBCUtil;
import com.mchange.v2.c3p0.ComboPooledDataSource;
// 使用配置檔案
public class C3P0Demo02 {

    @Test
    public void testC3P0() {

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            // 配置檔案 new了一個物件
            ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
            
            // 得到連線物件
            conn = dataSource.getConnection();

            String sql = "insert into account values(null, ?, ?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1, "bbb");
            ps.setInt(2, 10000);
            ps.executeUpdate();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps);
        }

    }
}

可以弄oracle:

<!-- This app is massive! -->
  <named-config name="oracle"> 
    <property name="acquireIncrement">50</property>
    <property name="initialPoolSize">100</property>
    <property name="minPoolSize">50</property>
    <property name="maxPoolSize">1000</property>

    <!-- intergalactoApp adopts a different approach to configuring statement caching -->
    <property name="maxStatements">0</property> 
    <property name="maxStatementsPerConnection">5</property>

    <!-- he`s important, but there`s only one of him -->
    <user-overrides user="master-of-the-universe"> 
      <property name="acquireIncrement">1</property>
      <property name="initialPoolSize">1</property>
      <property name="minPoolSize">1</property>
      <property name="maxPoolSize">5</property>
      <property name="maxStatementsPerConnection">50</property>
    </user-overrides>
  </named-config>

oracle:

ComboPooledDataSource dataSource = new ComboPooledDataSource();

DBUtils

什麼是DBUtils呢?怎麼用呢?

優化資料庫連線,使用C3P0:

package com.dashucoding.util;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JDBCUtil02 {
    
    static ComboPooledDataSource dataSource = null;

    static {
        dataSource = new ComboPooledDataSource();
    }
    /**
     * 獲取連線物件
     * @return
     * @throws SQLException 
     */
    public static Connection getConn() throws SQLException{
        
        return dataSource.getConnection();
    }
    
    /**
     * 釋放資源
     * @param conn
     * @param st
     * @param rs
     */
    public static void release(Connection conn , Statement st , ResultSet rs){
        closeRs(rs);
        closeSt(st);
        closeConn(conn);
    }
    public static void release(Connection conn , Statement st){
        closeSt(st);
        closeConn(conn);
    }

    
    private static void closeRs(ResultSet rs){
        try {
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            rs = null;
        }
    }
    
    private static void closeSt(Statement st){
        try {
            if(st != null){
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            st = null;
        }
    }
    
    private static void closeConn(Connection conn){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            conn = null;
        }
    }
}

DBUtils優化增刪改查方法

導包,兩行程式碼交你增刪改查,6666!

QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);

兩行.

效果

效果

package com.dashucoding.dbutils;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestDBUtils {
    @Test
    public void testInsert() throws SQLException {
//      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 

        // dbutils 簡化了CRUD的程式碼
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        
        /*
         * queryRunner.update(sql);
         * 增刪改
         * queryRunner.query(sql, rsh);
         * 查
         * */
        
        queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
    }

}
package com.dashucoding.dbutils;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestDBUtils {
    @Test
    public void testInsert() throws SQLException {
//      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 

        // dbutils 簡化了CRUD的程式碼
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        
        /*
         * queryRunner.update(sql);
         * 增刪改
         * queryRunner.query(sql, rsh);
         * 查
         * */
        
        queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
        queryRunner.update("delete from account where id = ?", 8);
        queryRunner.update("update account set money = ? where id = ?", 0, 10);
    }

}

查詢

效果

package com.dashucoding.dbutils;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.junit.Test;

import com.dashucoding.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestDBUtils {
    @Test
    public void testInsert() throws SQLException {
//      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 

        // dbutils 簡化了CRUD的程式碼
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        // 查詢的是一個Bean物件
        // new 匿名實現類->new介面的匿名實現類
        
        Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
            // 去執行查詢,查詢到的資料在result裡面,然後呼叫handle方法,使用者手動去封裝
            @Override
            public Account handle(ResultSet rs) throws SQLException {
                // TODO Auto-generated method stub
                Account account = new Account();
                
                while(rs.next()) {
                    String name = rs.getString("name");
                    int money = rs.getInt("money");
                    account.setName(name);
                    account.setMoney(money);
                }
                return account;
            }
            
        }, 1);
        System.out.println(account.toString());
        
        /*
         * queryRunner.update(sql);
         * 增刪改
         * queryRunner.query(sql, rsh);
         * 查
         * */
        
        /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
        queryRunner.update("delete from account where id = ?", 8);
        queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
    }

}

查詢優化

效果

一個物件: BeanHandler

一個集合裡面有很多物件: BeanListHandler

package com.dashucoding.domain;

public class Account {
    private String name;
    private int money;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getMoney() {
        return money;
    }
    public void setMoney(int money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account [name=" + name + ", money=" + money + "]";
    }
    
}
package com.dashucoding.dbutils;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.junit.Test;

import com.dashucoding.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestDBUtils {
    @Test
    public void testInsert() throws SQLException {
//      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 

        // dbutils 簡化了CRUD的程式碼
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        // 查詢的是一個Bean物件
        // new 匿名實現類->new介面的匿名實現類
        
        /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
            // 去執行查詢,查詢到的資料在result裡面,然後呼叫handle方法,使用者手動去封裝
            @Override
            public Account handle(ResultSet rs) throws SQLException {
                // TODO Auto-generated method stub
                Account account = new Account();
                
                while(rs.next()) {
                    String name = rs.getString("name");
                    int money = rs.getInt("money");
                    account.setName(name);
                    account.setMoney(money);
                }
                return account;
            }
            
        }, 1);
        System.out.println(account.toString());*/
        
        // 介面的實現類-> ResultSetHandler的實現類
        // Ctrl + t 實現類
        //ResultSetHandler
        
        // 一個物件查詢一個物件使用BeanHandler
        Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 1);
        System.out.println(account.toString());
        /*
         * queryRunner.update(sql);
         * 增刪改
         * queryRunner.query(sql, rsh);
         * 查
         * */
        
        /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
        queryRunner.update("delete from account where id = ?", 8);
        queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
    }

}

優化成兩行程式碼:

貼圖

Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 1);
System.out.println(account.toString());

查詢多個資料

效果

// 查詢多個物件
List<Account> list = queryRunner.query("select * from account",
                new BeanListHandler<Account>(Account.class));
for(Account account : list) {
 System.out.println(account.toString());
}
package com.dashucoding.dbutils;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;

import com.dashucoding.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class TestDBUtils {
    @Test
    public void testInsert() throws SQLException {
//      ComboPooledDataSource dataSource = new ComboPooledDataSource(); 

        // dbutils 簡化了CRUD的程式碼
        QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
        // 查詢的是一個Bean物件
        // new 匿名實現類->new介面的匿名實現類
        
        /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>() {
            // 去執行查詢,查詢到的資料在result裡面,然後呼叫handle方法,使用者手動去封裝
            @Override
            public Account handle(ResultSet rs) throws SQLException {
                // TODO Auto-generated method stub
                Account account = new Account();
                
                while(rs.next()) {
                    String name = rs.getString("name");
                    int money = rs.getInt("money");
                    account.setName(name);
                    account.setMoney(money);
                }
                return account;
            }
            
        }, 1);
        System.out.println(account.toString());*/
        
        // 介面的實現類-> ResultSetHandler的實現類
        // Ctrl + t 實現類
        //ResultSetHandler
        
        // 一個物件查詢一個物件使用BeanHandler
        /*Account account = queryRunner.query("select * from account where id = ?",
                new BeanHandler<Account>(Account.class), 1);
        System.out.println(account.toString());*/
        
        /*List<Account> account = queryRunner.query("select * from account",
                new BeanListHandler<Account>(Account.class));*/
        // 查詢多個物件
        List<Account> list = queryRunner.query("select * from account",
                new BeanListHandler<Account>(Account.class));
        for(Account account : list) {
            System.out.println(account.toString());
        }
        
        /*
         * queryRunner.update(sql);
         * 增刪改
         * queryRunner.query(sql, rsh);
         * 查
         * */
        
        /*queryRunner.update("insert into account values(null, ?, ?)", "bbb", 10000);
        queryRunner.update("delete from account where id = ?", 8);
        queryRunner.update("update account set money = ? where id = ?", 0, 10);*/
    }

}

小結

// 通過類的位元組碼,獲得該類的例項:
Account a = new Account();

Account a1 = Account.class.newInstance();

new BeanHandler<Account>(Account.class)

new BeanListHandler<Account>(Account.class)

小結

ResultSetHandler<T>

實現類:

貼圖

總結

事務,連線池,DBUtils

查詢:

貼圖

QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());

queryRunner.update();
queryRunner.query
  1. 事務
    髒讀
    不可重複讀
    幻讀

丟失更新 寫的問題
悲觀鎖 for update
樂觀鎖 ,新增欄位版本級別

4個隔離級別
讀未提交
讀已提交
可重複讀
可序列化

讀未提交,引發髒讀
讀已提交,引發不可重複讀,解決了髒讀

可重複讀,引發了幻讀,解決了髒讀,不可重複讀
可序列化(序列化),解決了髒讀,不可重複讀,幻讀,引發效率低下問題

資料庫連線池

  1. BCP -> 不使用配置 使用配置
  2. C3P0 -> 不使用配置 使用配置
  3. 自定義連線池 -> 飾者模式

結言

可在評論發表你的總結內容,做功課哦!

如果看了覺得不錯

點贊!轉發!

達叔小生:往後餘生,唯獨有你
You and me, we are family !
90後帥氣小夥,良好的開發習慣;獨立思考的能力;主動並且善於溝通
簡書部落格: 達叔小生
https://www.jianshu.com/u/c785ece603d1

結語

  • 下面我將繼續對 其他知識 深入講解 ,有興趣可以繼續關注
  • 小禮物走一走 or 點贊

相關文章