JDBC

cherry...a發表於2020-10-17

JDBC

JDBC:java database connectivity java 連線資料庫

JDBC其實就是Java定義的一套和資料庫建立連線的規範(介面),那麼各家資料庫廠商,想要java去操作各家的資料庫,必須實現這套介面,我們把資料庫廠商寫的這套實現類稱之為資料庫驅動。

package com.itheima;

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

public class demo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //JDBC:快速入門
        //1.引入MySQL的驅動jar包,記得依賴一下。
        //2.載入驅動
        //3.獲取連線物件。
        //4.獲取操作物件
        //5.傳送SQL語句進行操作。
        //6.釋放資源。
        //2.載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        //3.獲取連線物件。
        String url="jdbc:mysql://localhost:3306/mydb";
        String username="root";
        String password="123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        //4.獲取操作物件
        Statement statement = conn.createStatement();
        //5.傳送SQL語句進行操作。
        String sql="insert into product(name) values('褲子') ";
        //執行executeUpdate(sql) 增刪改的語句
        int l = statement.executeUpdate(sql);
        if(l>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失敗");
        }
        //6.釋放資源。
        conn.close();
        statement.close();
    }
}

 Class.forName("com.mysql.jdbc.Driver"); 載入驅動,也可以省略不寫
 註冊驅動這個動作是Driver裡面有個靜態程式碼塊在做
    static {
            try {
                DriverManager.registerDriver(new Driver());
            } catch (SQLException var1) {
                throw new RuntimeException("Can't register driver!");
            }
        }
        

幾個類的介紹

類 DriverManager Java提供的管理一組 JDBC 驅動程式的基本服務。
介面 Connection 試圖建立到給定資料庫URL的連線
介面 Statement 用於執行靜態程式碼 SQL 語句並返回它所生成結果的物件。
boolean b = statement.execute(sql);//用來執行所有的SQL語句 返回:
如果第一個結果為 ResultSet 物件,則返回 true;如果其為更新計數或者不存在任何結果,則返回 false 
  int i = statement.executeUpdate(sql);//用來執行DML語句 用來對錶中資料進行增刪改 返回值是影響的行數
        statement.executeQuery(sql);//用來執行DQl語句
      
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class demo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        //3.獲取連線物件
        //DriverManager 管理一組 JDBC 驅動程式的基本服務。
        // 試圖建立到給定資料庫 URL 的連線。DriverManager 試圖從已註冊的 JDBC 驅動程式集中選擇一個適當的驅動程式。
        //URL:統一資源定位符,格式:協議://ip:埠/具體的資源路徑
        //主協議:子協議://ip:埠/資源路徑
        //如果是本地連線:ip和埠可以省略不寫  "jdbc:mysql:///mydb"
        // String url = "jdbc:mysql://192.168.17.123:3306/mydb"; 寫ip MySQL需要設定了遠端訪問
        //獲取連線物件
        String url="jdbc:mysql://localhost:3306/mydb";
        String username="root";
        String password="123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        //Connection 介面 與特定資料庫的連線(會話)。在連線上下文中執行 SQL 語句並返回結果。
        //獲取操作物件
        Statement statement = conn.createStatement();
        // 介面 Statement 用於執行靜態 SQL 語句並返回它所生成結果的物件。
        //5.傳送SQL語句進行操作。
        String sql="insert into product(name) values('水果') ";
        //executeUpdate(sql); 執行的 DML 語句
        //ResultSet executeQuery(String sql) 執行DQL語句
        // 執行給定的 SQL 語句,該語句返回單個 ResultSet 物件。
        // boolean execute (String sql)執行任意的SQL語句。
        int i = statement.executeUpdate(sql);
        if(i>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失敗");
        }
        //釋放資源
        conn.close();
        statement.close();
    }
}

結果集物件 ResultSet

結果集物件是執行了查詢語句之後返回的一個查詢結果物件。
ResultSet 物件具有指向其當前資料行的游標。 最初,游標被置於第一行之前。next 方法將游標移動到下一行;因為該方法在 ResultSet 物件沒有下一行時返回 false,所以可以在 while迴圈中使用它來迭代結果集。

 while (resultSet.next()){
            //引數就是資料庫中的欄位序號 從1開始
            //String username = resultSet.getString(1);
            //int age = resultSet.getInt(2);
            //通過欄位名來獲取欄位的值
            String username = resultSet.getString("username");
            int age = resultSet.getInt("age");
            //System.out.println(username+"==="+age);
            //我們從資料庫中取出了資料,就是為了要使用這些資料,那我們就要對這些資料進行封裝
            Student student = new Student(username, age);
            list.add(student);
        }
package com.itheima;

public class MyLog {
    private int id;
    private String name;
    private int price;

    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 int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "MyLog{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
package com.itheima;

import com.sun.org.apache.regexp.internal.RE;

import java.sql.*;
import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        Statement statement = conn.createStatement();
        String sql = "select * from product";
        //執行DQL語句
        //ResultSet 結果集物件,封裝的的查詢出的多條結果
        //resultSet.next() 往下移動指標,如果沒有了資料,就返回false;
        ResultSet resultSet = statement.executeQuery(sql);
        ArrayList<MyLog> list = new ArrayList<>();
        while (resultSet.next()) {
            //可以傳入列名,或者列號
            int id = resultSet.getInt("id");
            //   列號從1開始 int anInt = resultSet.getInt(1);
            String name = resultSet.getString("name");
            int price = resultSet.getInt("price");
            //將資料查詢出來列印在控制檯
            // System.out.println(id+"--"+name+"--"+price);
            //我們從資料庫查出了資料,要在別的地方用,你應該把查詢出的資料封裝起來。
            MyLog myLog = new MyLog();
            myLog.setId(id);
            myLog.setName(name);
            myLog.setPrice(price);
        //把資源放到集合中
            list.add(myLog);

        }
        System.out.println(list);
        conn.close();
        statement.close();
        resultSet.close();
    }
}

資料庫實現使用者登入
package com.itheima;

import java.sql.*;
import java.util.Scanner;
//登入  資料儲存在資料庫中cherry
public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入使用者名稱");
        String name = sc.nextLine().trim();
        System.out.println("請輸入使用者密碼");
        String pwd = sc.nextLine().trim();
        // 查詢資料庫比對是否輸入正確
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb2";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        Statement statement = conn.createStatement();
        //定義sql語句
        String sql = "select *from user where username='+name+'and password='+pwd+'";
        ResultSet resultSet = statement.executeQuery(sql);
        if (resultSet.next()) {
            System.out.println("登入成功");
        } else {
            System.out.println("登入失敗");
        }
        //釋放資源
        conn.close();
        statement.close();
        resultSet.close();
    }
}

SQL隱碼攻擊

SQL隱碼攻擊是指web應用程式對使用者輸入資料的合法性沒有判斷或過濾不嚴。
攻擊者可以在web應用程式中將事先定義好的查詢語句的結尾添上額外的SQL語句,
在管理員不知情的情況下實現非法操作,以此來實現欺騙資料庫伺服器執行非授權的任意查詢,從而進一步得到相應的資料資訊。

預編譯操做物件 PreparedStatement

這個操作物件,可以在安全方面防止SQL隱碼攻擊
使用步驟:1.conn.prepareStatement(sql);
        2.sql語句中的欄位的值用?問號佔位
        3.給sql語句中的問號賦值
        
         //SQL語句中的值 全部用 ? 問號佔位
        String sql="SELECT * FROM users WHERE username=? AND PASSWORD=?";
        //獲取一個預編譯操作物件  PreparedStatement
        PreparedStatement preparedStatement = conn.prepareStatement(sql); //把SQL語句給給這個預編譯操作物件
        //下來給問號賦值 參1.問號的順序,從1開始數 引數2 問號的值
        preparedStatement.setString(1,uname);
        preparedStatement.setString(2,pwd);

        ResultSet resultSet = preparedStatement.executeQuery(); //這裡就不要再傳入SQL語句
package com.itheima;

import java.sql.*;

public class Test3 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb2";
        String username = "root";
        String password = "123456";
        //建立連線
        Connection connection = DriverManager.getConnection(url, username, password);
        //定義編譯語句
        String sql= "insert into user(username,password) values(?,?)";
        String sql2="select * from user where username='lisa1'";
        //獲取預編譯物件
        PreparedStatement preparedStatement2 = connection.prepareStatement(sql2);
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
       preparedStatement.setString(1,"lisa1");
       preparedStatement.setString(2,"654321");
       //開始查詢是否存在
        ResultSet resultSet = preparedStatement2.executeQuery();
        if(resultSet.next()){
            //存在
            System.out.println("註冊失敗");
        }else{
            //不存在  開始註冊
            int i = preparedStatement.executeUpdate();
            if(i>0){
                System.out.println("插入成功");
            }else{
                System.out.println("插入失敗");
            }
        }

    }
}

批處理

在插入大量的資料的時候使用批處理來做。
statement.addBatch();//新增批處理,先將資料快取起來
  statement.executeBatch();//執行批處理
  statement.clearBatch();//清空快取

JDBC 呼叫儲存過程和函式 CallableStatement

呼叫儲存過程 {call <procedure-name>[(<arg1>,<arg2>, ...)]}
 		Connection conn = JDBCUtils.getConnection();
        String sql="{call testPro(?,?)}"; //輸入或輸出引數用?佔位
        CallableStatement prepareCall = conn.prepareCall(sql);
        //給輸入引數設定值
        prepareCall.setInt(1,7369);
        //如果有輸出引數我們需要註冊輸出引數
        prepareCall.registerOutParameter(2, Types.INTEGER);
        boolean b = prepareCall.execute();
        //獲取輸出結果
        int r = prepareCall.getInt(2);
        System.out.println(r);
        //釋放資源
        JDBCUtils.close(conn,prepareCall);
        
        
 呼叫自定義函式 {?=call<procedure -name >[( < arg1 >,<arg2 >, ...)]}
 		String sql="{?=call testFun(?)}";
        CallableStatement callableStatement = conn.prepareCall(sql);
        //設定輸入引數
        callableStatement.setInt(2,7902);
        //註冊返回值
        callableStatement.registerOutParameter(1, Types.INTEGER);
        callableStatement.execute();
        //獲取返回的結果
        int r = callableStatement.getInt(1);
        System.out.println("結果是:"+r);
        //釋放資源
        JDBCUtils.close(conn,callableStatement);

獲取自增長鍵的值

要獲取自增長鍵的值 需要在獲取操作物件時宣告一個引數 Statement.RETURN_GENERATED_KEYS
 PreparedStatement preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
 
 2.當資料插入成功後,就可以取出這個自增長鍵的值
  //獲取自增長鍵的結果集
            ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
            while (generatedKeys.next()){
                keyValue = generatedKeys.getInt(1);
            }
            
 3.你在其他表中就可以使用這個自增長鍵的值         

事務

基本 概念:事務是指一組最小邏輯的操作單元,裡面有多個操作組成。組成事務的每一部分必須要同時提交成功,如果有一個操作失敗,整個操作就會回滾。

事務ACID特性
原子性(Atomicity):原子性是指事務是一個不可分割的工作單元,事務中的操作要麼都發生,要麼都不發生。
一致性(Consistency):事務必須使資料庫從一個一致性狀態變換到另一個一致性狀態。
隔離性(isolation):事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的資料所干擾,多個併發事務之間要相互隔離。
永續性(Durability):永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
一般情況下,Connection物件處於自動提交的模式下,這意味著它在執行每個語句後都會自動提交更改。
如果禁用了自動提交模式,那麼提交更改就必須顯示呼叫。
commit 方法;否則無法儲存資料庫更改。
//void setAutoCommit ( boolean autoCommit) throws SQLException將此連線的自動提交模式設定為給定狀態。如果連線處於自動提交模式下,則它的所有 SQL 語句將被執行並作為單個事務提交。否則,它的 SQL 語句將聚集到事務中,
//直到呼叫 commit 方法或 rollback 方法為止。預設情況下,新連線處於自動提交模式。
模式銀行的轉賬
Connection conn1= JDBCUtils.getConnection();

        //減錢
        String sql1="update bank set money=money-1000 where username='zhangsan'";
        //加錢
        String sql2="update bank set money=money+1000 where username='lisi'";
        //獲取操作物件
        PreparedStatement preparedStatement1 = conn1.prepareStatement(sql1);
        PreparedStatement  preparedStatement2= conn1.prepareStatement(sql2);
        //執行操作 減去錢 自動開啟了一個事務 執行完 提交事務,資料就持久化
        preparedStatement1.executeUpdate();
        //模擬異常
         System.out.println(1/0);
        //加上錢  自動開啟了一個事務 提交事務,資料就持久化
        preparedStatement2.executeUpdate();
  conn1= JDBCUtils.getConnection();
            //把自動提交事務,改成手動提交事務。
            conn1.setAutoCommit(false);
            //減錢
            String sql1="update bank set money=money-1000 where username='zhangsan'";
            //加錢
            String sql2="update bank set money=money+1000 where username='lisi'";
            //獲取操作物件
            PreparedStatement preparedStatement1 = conn1.prepareStatement(sql1);
            PreparedStatement  preparedStatement2= conn1.prepareStatement(sql2);
            //執行操作 減去錢 自動開啟了一個事務 執行完 提交事務,資料就持久化
            preparedStatement1.executeUpdate();
            //模擬異常
            System.out.println(1/0);
            //加上錢  自動開啟了一個事務 自動提交事務,資料就持久化
            preparedStatement2.executeUpdate();

            //預設清空下,減錢 是一個事務,加錢是一個事務,我們應該把減錢和加錢這兩部操作,放到同一個事務中。
        } catch (Exception e) {
            e.printStackTrace();
            //一旦遇到異常,就回滾事務
            try {
                conn1.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            try {
                conn1.commit(); //手動提交事務

                //釋放資源
            } catch (SQLException e) {
                e.printStackTrace();
            }


        }

事務的隔離級別

不考慮隔離性會出現的讀問題:

髒讀:在一個事務中讀取到另一個事務沒有提交的資料。

不可重複讀:在一個十五中,兩次查詢的結果不一致,這種情況主要針對的是update操作,不可重複讀,是指在資料庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不同的資料。

虛讀:也稱為幻讀,在一個事務中,兩次查詢的結果不一致 這個主要針對的是insert操作,mysql預設避免。

通常可以通過設定資料庫的隔離級別來避免上面的問題;

read uncommitted 讀未提交 上面的三個問題都會出現
read committed 讀已提交 可以避免髒讀的發生 Oracle 預設級別
repeatable read 可重複讀 可以避免髒讀和不可重複讀的發生 MySQL 預設級別
serializable 序列化 可以避免所有的問題

四種隔離級別的效率:

read uncommitted>read committed>repeatable read>serializable

四種隔離級別的安全性
read uncommitted<read committed<repeatable read<serializable

開發中是不允許髒讀的發生的;

mysql中預設級別:repeatable read
oracle中預設級別:read committed

模擬銀行操作:
 Connection conn1 =null;
        Savepoint savepoint=null;
        try {
             conn1= JDBCUtils.getConnection();
            //把自動提交事務,改成手動提交事務。
            conn1.setAutoCommit(false);
            //減錢
            String sql1="update bank set money=money-1000 where username='zhangsan'";
            //加錢
            String sql2="update bank set money=money+1000 where username='lisi'";
            //獲取操作物件
            PreparedStatement preparedStatement1 = conn1.prepareStatement(sql1);
            PreparedStatement  preparedStatement2= conn1.prepareStatement(sql2);
            //執行操作 減去錢 自動開啟了一個事務 執行完 提交事務,資料就持久化
            preparedStatement1.executeUpdate();
            //模擬異常
            //System.out.println(1/0);
            //加上錢  自動開啟了一個事務 自動提交事務,資料就持久化
            preparedStatement2.executeUpdate();


            //設定回滾點
             savepoint = conn1.setSavepoint();

            System.out.println("----------------------------------------");

            //減錢
            String sql3 = "update bank set money=money-500 where username='zhangsan'";
            //加錢
            String sql4 = "update bank set money=money+500 where username='lisi'";
            //獲取操作物件
            PreparedStatement preparedStatement3 = conn1.prepareStatement(sql3);
            PreparedStatement preparedStatement4 = conn1.prepareStatement(sql4);

            //執行操作 減去錢 自動開啟了一個事務 執行完 提交事務,資料就持久化
            preparedStatement3.executeUpdate();
            //模擬異常
             System.out.println(1/0);
            //加上錢  自動開啟了一個事務 自動提交事務,資料就持久化
            preparedStatement4.executeUpdate();


            //預設清空下,減錢 是一個事務,加錢是一個事務,我們應該把減錢和加錢這兩部操作,放到同一個事務中。
        } catch (Exception e) {
            e.printStackTrace();
            //一旦遇到異常,就回滾事務
            try {
              //  conn1.rollback();
                conn1.rollback(savepoint); //回滾到,回滾點的地方
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            try {
                conn1.commit(); //手動提交事務

                //釋放資源
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
常見連線池的使用

連線池:通過連線池預先同資料庫建立一些連線,放在記憶體中,應用程式需要建立資料庫連線時到連線池中申請就行,使用完畢之後再歸還到連線池中。

資料庫連線池負責分配,管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個,釋放空間時間超過最大空閒時間的資料庫連線來避免避免因為沒有釋放資料庫連線而引起的資料庫連線漏洞了,這項技術能明顯提高對資料庫操作的效能。

連線池基本的思想是在系統初始化的時候,將資料庫連線作為物件儲存在記憶體中,當使用者需要訪問資料庫時,並非建立一個新的連線,而是從連線池中取出一個已建立的空閒連線物件。使用完畢後,使用者也並非將連線關閉,而是將連線放回連線池中,以供下一個請求訪問使用。而連線的建立、斷開都由連線池自身來管理。同時,還可以通過設定連線池的引數來控制連線池中的初始連線數、連線的上下限數以及每個連線的最大使用次數、最大空閒時間等等。也可以通過其自身的管理機制來監視資料庫連線的數量、使用情況等

三種連線池的介紹

DBCP連線池
DBCP(DataBase Connection Pool)資料庫連線池,
 是Java資料庫連線池的一種,由Apache開發,通過資料庫連線池,
    可以讓程式自動管理資料庫連線的釋放和斷開
 使用步驟:
			1.匯入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.jar)
			2.使用api
				a.硬編碼
					a.硬編碼(不推薦)   
    
    //建立連線池
		BasicDataSource ds = new BasicDataSource();
		
		//配置資訊
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql:///day07");
		ds.setUsername("root");
		ds.setPassword("1234");
		
		Connection conn=ds.getConnection();
		String sql="insert into category values(?,?);";
		PreparedStatement st=conn.prepareStatement(sql);
		//設定引數
		st.setString(1, "c011");
		st.setString(2, "飲料");
		
		int i = st.executeUpdate();
		System.out.println(i);


採用配置檔案的方式
		//存放配置檔案
		Properties prop = new Properties();
		prop.load(new FileInputStream("src/dbcp.properties"));
		//設定
		//prop.setProperty("driverClassName", "com.mysql.jdbc.Driver");
		
		//建立連線池
		DataSource ds = new BasicDataSourceFactory().createDataSource(prop);
		
		Connection conn=ds.getConnection();
		String sql="insert into category values(?,?);";
		PreparedStatement st=conn.prepareStatement(sql);
		
		//設定引數
		st.setString(1, "c012");
		st.setString(2, "飲料1");
		
		int i = st.executeUpdate();
		System.out.println(i);
採用該連線池實現查詢功能:
package com.itheima.demo;

import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class DBCPTest {
    public static void main(String[] args) throws Exception {
        Properties pp = new Properties();
        pp.load(new FileReader("dbcp.properties"));
        DataSource ds = BasicDataSourceFactory.createDataSource(pp);
        Connection conn = ds.getConnection();
        //建立連線物件

        PreparedStatement preparedStatement = conn.prepareStatement("select * from user");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            int anInt = resultSet.getInt(1);
            System.out.println(anInt);
            String string = resultSet.getString(2);
            System.out.println(string);

        }
        preparedStatement.close();
        resultSet.close();

    }
}

C3P0連線池
C3P0是一個開源的JDBC連線池,它實現了資料來源和JNDI繫結,支援JDBC3規範和JDBC2的標準擴充套件。目前使用它的開源專案有Hibernate、Spring等。
c3p0與dbcp區別
dbcp沒有自動回收空閒連線的功能
c3p0有自動回收空閒連線功能

使用步驟:
			1.匯入jar包(c3p0-0.9.1.2.jar)
			2.使用api
		方式1:硬編碼
		ComboPooledDataSource ds = new ComboPooledDataSource();
		//設定基本引數
		ds.setDriverClass("com.mysql.jdbc.Driver");
		ds.setJdbcUrl("jdbc:mysql:///day07");
		ds.setUser("root");
		ds.setPassword("1234");
		
		Connection conn=ds.getConnection();
		String sql="insert into category values(?,?);";
		PreparedStatement st=conn.prepareStatement(sql);
		
		//設定引數
		st.setString(1, "c013");
		st.setString(2, "毒藥");
		
		int i = st.executeUpdate();
		System.out.println(i);
		
採用配置檔案的方式

b.配置檔案
					要求1:配置檔案的名稱:c3p0.properties 或者 c3p0-config.xml
					要求2:配置檔案的路徑:src下
				
					編碼只需要一句話
						new ComboPooledDataSource()//使用預設的配置
						//可以切換xml配置檔案中的標籤 來載入不同的配置比如更換Orecal的資料庫的配置
						new ComboPooledDataSource(String configName)//使用命名的配置 若配置的名字找不到,使用預設的配置
package com.itheima.demo;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class C3P0Test {
    public static void main(String[] args) throws SQLException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        Connection connection = ds.getConnection();
       // System.out.println(connection);
        String sql="select *from user'";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){

            String name = resultSet.getString(1);
            String pwd = resultSet.getString(2);
            System.out.println("查詢成功");
            System.out.println(name);
            System.out.println(pwd);
        }
preparedStatement.close();
        resultSet.close();


    }
}
 //如果傳入 xml配置檔案中的第二配置名,那就讀取第二配置
        ComboPooledDataSource ds = new ComboPooledDataSource("myname");
Druid 阿里德魯伊連線池
 DRUID是阿里巴巴開源平臺上一個資料庫連線池實現,它結合了C3P0、DBCP、PROXOOL等DB池的優點,同時加入了日誌監控,可以很好的監控DB池連線和SQL的執行情況,可以說是針對監控而生的DB連線池(據說是目前最好的連線池,不知道速度有沒有BoneCP快)。


使用步驟,匯入德魯伊的jar包
  1.採用硬編碼的方式
    	//採用硬編碼的方式來建立連線池
        DruidDataSource dataSource = new DruidDataSource();
        //設定引數
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/crm");
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(1);
        dataSource.setMaxActive(10);
        //獲取連線物件
        DruidPooledConnection connection = dataSource.getConnection();
        System.out.println(connection);


   2.採用配置檔案的方式,
      a.引入配置檔案
      b.載入配置檔案
       //採用載入配置檔案的方式
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/db_server.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        Connection conn = dataSource.getConnection();
        System.out.println(conn);
package com.itheima.demo;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
public class DruidTest {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileReader("druid.properties"));
        DataSource ds = DruidDataSourceFactory.createDataSource(properties);
        Connection connection = ds.getConnection();
       String sql="select * from user where username='cherry'";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
            String name = resultSet.getString(1);
            String pwd = resultSet.getString(2);
            System.out.println(name);
            System.out.println(pwd);


        }
        resultSet.close();
        preparedStatement.close();
    }
}

Commons DbUtils是Apache組織提供的一個對JDBC進行簡單封裝的開源工具類庫,
使用它能夠簡化JDBC應用程式的開發,同時也不會影響程式的效能。 

使用步驟:
		1.匯入jar包(commons-dbutils-1.4.jar)
		2.建立一個queryrunner類
			queryrunner作用:操作sql語句
				構造方法:
					new QueryRunner(Datasource ds);
		3.編寫sql
		4.執行sql
			query(..):執行r操作
			update(...):執行cud操作
			
	使用步驟
		// 建立物件
		QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
		// 定義sql
		String sql = "insert into bank(username,money) values(?,?)";
		// 執行sql
		runner.update(sql,"趙六",500);
		....
	執行查詢後返回的結果集
	ResultSetHandler:封裝結果集 介面
	BeanListHandler, 將查詢結果的每一條記錄封裝成指定的bean物件,將每一個bean物件放入list中 返回.