連接池:
一、什么是連接池:
1. JDBC訪問數據庫的步驟:
1) 創建連接 --> 2) 訪問數據庫 --> 3) 關閉連接
2. 使用連接池解決
1) 由服務器在啟動的時候,就創建好一定數據的連接對象。
2) 用戶從創建好的連接池中,直接取出一個連接對象即可
3) 如果一個連接對象使用完畢,則將連接對象放回到連接池中。
二、數據庫連接池API:
1. 數據源接口
javax.sql.DataSource 數據源(連接池),所有的連接池都必須要實現這個接口。
2. 得到連接的方法:
Connection getConnection() 不指定參數,得到一個連接對象
3. 連接池常用的初始參數:(所有的連接池都有默認參數)
1) 初始連接數,連接池創建的時候,創建的連接對象
2) 最大連接數,連接池中連接數上限。
3) 最大等待時間,如果超時,拋出異常。如果連接池中沒有連接對象,等待多久。
4) 最大空閑等待時間,如果一個用戶得到了連接對象,多久沒有發送SQL語句,就會被連接池回收。
C3P0連接池:
1) 開放源代碼,免費使用
2) Hibernate框架(訪問數據庫)中默認使用的連接池
1. 使用步驟:
1) 導包 c3p0-0.9.5.2.jar 、mchange-commons-java-0.2.12.jar
2) 設置參數(通過源代碼或通過配置文件)
要設置兩類參數:
2.1) 數據庫連接參數(用戶名,密碼,URL,驅動)
2.2) 數據庫連接池的參數
3) 得到連接池(數據源)
4) 從連接池中得到連接對象
c3po連接池使用1 public static void main(String[] args) throws Exception { 2 // 1.創建數據源對象 3 ComboPooledDataSource ds = new ComboPooledDataSource(); 4 // 2. 設置數據庫的連接參數 5 // 用戶名,密碼,URL,驅動 6 ds.setUser("root"); 7 ds.setPassword("root"); 8 ds.setJdbcUrl("jdbc:mysql://localhost:3306/day25"); 9 ds.setDriverClass("com.mysql.jdbc.Driver"); 10 // 3. 設置連接池的參數 11 ds.setInitialPoolSize(5); // 初始連接數 12 ds.setMaxPoolSize(10); // 最大連接數 13 ds.setCheckoutTimeout(2000); // 最長等待時間,單位:毫秒 14 ds.setMaxIdleTime(1000); // 最長空閑等待時間 15 // 4. 得到連接對象 16 for (int i = 1; i <= 11; i++) { 17 Connection conn = ds.getConnection(); 18 System.out.println("第" + i + "個連接:" + conn); 19 //第5個連接釋放 20 if (i ==5) { 21 conn.close(); 22 } 23 } 24 }使用配置文件配置參數:
1. 使用配置文件的好處:
1) 因為所有的這些配置參數都寫在源碼中,以后修改不方便。
2) 配置與源碼是耦合在一起
2. 配置文件的要求:
1) 文件名:c3p0-config.xml
2) 位置:放在類路徑下,放在src目錄下
3) 在一個配置文件中,可以有多個配置:
3.1) 默認配置:如果沒有指定配置名,則使用默認配置
3.2) 命名配置:如果指定了配置名,則使用指定的配置
3. 多個不同配置的好處:
1) 可以使用不同的連接池的配置參數
2) 可以連接不同的數據庫。如:db1, db2
3) 可以使用不同廠商的數據庫,如:MySQL,Oracle
2. C3P0連接池的工具類:
1). 創建私有靜態數據源成員變量
2). 創建公有的得到數據源的方法
3). 創建得到連接對象的方法

1 /** 2 * 連接池的工具類 3 * 4 * @author NewBoy 5 * 6 */ 7 public class C3P0Util { 8 /** 9 * 1. 創建私有靜態數據源成員變量 10 */ 11 private static ComboPooledDataSource ds = new ComboPooledDataSource(); 12 13 /** 14 * 2. 創建公有的得到數據源的方法 15 * @return 16 */ 17 public static DataSource getDataSource() { 18 return ds; 19 } 20 21 /** 22 * 3. 創建得到連接對象的方法 23 * @return 24 */ 25 public static Connection getConnection() { 26 try { 27 return ds.getConnection(); 28 } catch (SQLException e) { 29 e.printStackTrace(); 30 } 31 return null; 32 } 33 34 }
DBCP連接池: (DataBase Connection Pool 數據庫連接池)
1) 廠商:apache基金組織
2) 開放源代碼,免費
3) Tomcat(Web服務器),默認使用的就是DBCP連接池
3. 使用步驟:
1) 下載包
commons-dbcp-1.4.jar 數據庫連接池的核心包
commons-pool-1.5.6.jar 輔導支持包
2) 編寫代碼,創建連接池
public class BasicDataSource implements DataSource
3) 設置參數
3.1) 數據庫的連接參數
3.2) 連接池的參數
4) 通過數據源得到連接對象
dbcp示例1 public class Demo1 { 2 3 public static void main(String[] args) throws SQLException { 4 // 1.導包commons-dbcp-1.4.jar 數據庫連接池的核心包 commons-pool-1.5.6.jar 輔導支持包 5 // 2) 編寫代碼,創建連接池 6 BasicDataSource ds = new BasicDataSource(); 7 // 3) 設置參數 8 // 3.1) 數據庫的連接參數(用戶名,密碼,URL,驅動) 9 ds.setUsername("root"); 10 ds.setPassword("root"); 11 ds.setUrl("jdbc:mysql://localhost:3306/day25"); 12 ds.setDriverClassName("com.mysql.jdbc.Driver"); 13 // 3.2) 連接池的參數(初始連接數,最大連接數,最長等待時間,最大等待個數) 14 ds.setInitialSize(5); 15 ds.setMaxActive(10); 16 ds.setMaxWait(2000); 17 ds.setMaxIdle(3); 18 // 4) 通過數據源得到連接對象 19 for (int i = 1; i <=11; i++) { 20 //Cannot get a connection, pool error Timeout waiting for idle object 21 Connection conn = ds.getConnection(); 22 System.out.println("第" + i + "個連接:" + conn.hashCode()); 23 if (i == 5) { 24 conn.close(); //關閉了一個連接 25 } 26 } 27 } 28 }DBCP使用配置文件加載
1. 配置文件
文件名:xxx.properties
內容:屬性名=屬性值
1) 屬性名:與set方法的名字相同,去掉set,首字母小寫,如:setInitialSize 寫成 initialSize
2) 位置:建議放在src目錄下,使用類加載器得到資源文件
dbcp配置文件1 # database connection information 2 username=root 3 password=root 4 url=jdbc:mysql://localhost:3306/day25 5 driverClassName=com.mysql.jdbc.Driver 6 # database connect pool information 7 initialSize=5 8 maxActive=10 9 maxWait=2000 10 maxIdle=3
dbcp示例1 代碼要點: 2 1) 使用Properties類加載屬性文件 3 2) 通過類路徑加載輸入流 4 3) 通過工廠對象的靜態方法,得到DataSource連接池對象 5 4) 通過BasicDataSource類得到連接對象 6 7 代碼: 8 public static void main(String[] args) throws Exception { 9 // 1) 使用Properties類加載屬性文件 10 Properties info = new Properties(); 11 // 2) 通過類路徑加載輸入流 12 info.load(Demo2.class.getClassLoader().getResourceAsStream("dbcp.properties")); 13 // 3) 通過工廠對象的靜態方法,得到DataSource連接池對象 14 BasicDataSource ds = (BasicDataSource) BasicDataSourceFactory.createDataSource(info); 15 // 4) 通過BasicDataSource類得到連接對象 16 for (int i = 1; i <= 11; i++) { 17 Connection conn = ds.getConnection(); 18 System.out.println(conn.hashCode()); 19 //釋放一個 20 if (i==3) { 21 conn.close(); 22 } 23 } 24 }
DbUtils工具
1. 組織: apache基金會
2. 特點:
1) 對JDBC進行封裝,學習成本低,容易上手。
2) 效率接近於直接使用JDBC的代碼
3) 幾乎所有增刪改查操作,都可以一句話搞定
一、主要類介紹:
1. 導入jar包:commons-dbutils-1.6.jar
2. DbUtils類:
1) 所有的方法都是靜態方法
2) 一組釋放資源的方法
static void close(Connection conn)
static void close(ResultSet rs)
static void close(Statement stmt)
static void closeQuietly(Connection conn)
static void closeQuietly(Connection conn, Statement stmt, ResultSet rs)
3. QueryRunner類(重點):
進行增刪改查的類
4. ResultSetHandler接口:
用於處理查詢的結果集,並且對結果集再次進行封裝。
ResultSet -> List<Student>
二. QueryRunner類的主要方法
1. 方式一:
1) 傳入數據源的構造方法:
QueryRunner(DataSource ds)
2) 增刪改的方法
int update(String sql) SQL語句
int update(String sql, Object... params) SQL語句中有多個占位符,參數用來替換占位符的真實的值
int update(String sql, Object param) SQL語句中只有一個占位符,參數用來替換占位符的真實的值
返回影響的行數
3) 無需關閉連接
因為update方法的內部已經關閉了連接對象

1 public class Demo1 { 2 // 1.創建QueryRunner類,在構造方法中傳入了數據源 3 QueryRunner runner = new QueryRunner(C3P0Util.getDataSource()); 4 5 @Test 6 public void testAdd() throws SQLException { 7 // 2. 向數據庫中添加一條記錄 8 runner.update("insert into student (name,gender,birthday) values (?,?,?)", "唐僧", "男", 9 java.sql.Date.valueOf("2000-11-11")); 10 } 11 12 @Test 13 public void testUpdate() throws SQLException { 14 //將id為2的學生,性別改成女 15 runner.update("update student set gender=? where id=?", "女", 2); 16 } 17 18 @Test 19 public void testDelete() throws SQLException { 20 //刪除姓名為:龜仙人記錄 21 runner.update("delete from student where name=?", "龜仙人"); 22 } 23 }
2. 方式二:
1) 無參的構造方法:new QueryRunner()
2) 增刪改的方法
傳入了連接對象
int update(Connection conn, String sql) 只有SQL語句
int update(Connection conn, String sql, Object... params) 多個參數,有多個占位符
int update(Connection conn, String sql, Object param) 一個參數,一個占位符
3) 關閉連接
需求自己手動關閉連接

1 // 創建QueryRunner類 2 QueryRunner runner = new QueryRunner(); 3 4 @Test 5 public void testAdd() throws SQLException { 6 // 得到連接對象 7 Connection conn = C3P0Util.getConnection(); 8 // 添加1條記錄 9 int row = runner.update(conn, "insert into student(name,gender,birthday) values (?,?,?)", "小喬", "女", 10 java.sql.Date.valueOf("2000-03-20")); 11 //連接對象需要自己關閉 12 DbUtils.close(conn); 13 System.out.println(row); 14 }
3. 查詢有關的方法(需要時實現ResultSetHandler接口)
1) 沒有連接對象的
<T> T query(String sql, ResultSetHandler<T> rsh)
傳入SQL語句和結果集的處理類
<T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
sql: SQL語句
rsh:結果集處理類
params:替換占位符的參數
2) 有連接對象的
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh)
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
三. ResultSetHandler接口
1. 方法:
T handle(ResultSet rs) 將結果集轉成一個對象

1 實現類: 2 示例:查詢學生信息表中1條記錄 3 4 public class Demo3 { 5 //創建QueryRunner對象 6 QueryRunner runner = new QueryRunner(C3P0Util.getDataSource()); 7 8 @Test 9 public void testQueryStudent() throws SQLException{ 10 //通過id查詢一個學生 11 Student student = runner.query("select * from student where id=?", new StudentHandler(), 3); 12 System.out.println(student); 13 } 14 } 15 16 public class StudentHandler implements ResultSetHandler<Student> { 17 @Override 18 public Student handle(ResultSet rs) throws SQLException { 19 //如果有結果集 20 Student student = new Student(); 21 if (rs.next()) { 22 student.setId(rs.getInt("id")); 23 student.setName(rs.getString("name")); 24 student.setGender(rs.getString("gender")); 25 student.setBirthday(rs.getDate("birthday")); 26 } 27 return student; 28 } 29 }
2. 常用的實現類(已經實現了ResultSetHandler接口):
1) 封裝成JavaBean:查詢一條記錄的時候
前提:表的列名與類的屬性名相同
BeanHandler<>();
2) 封裝成List<JavaBean>
BeanListHandler<>();
查詢多條記錄的時候
3) 單行單列:用於聚合函數查詢
ScalarHandler<>();

1 public class Demo3 { 2 3 // 創建QueryRunner對象 4 QueryRunner runner = new QueryRunner(C3P0Util.getDataSource()); 5 6 @Test 7 public void testQueryStudent() throws SQLException { 8 // 通過id查詢一個學生 9 Student student = runner.query("select * from student where id=?", new StudentHandler(), 3); 10 System.out.println(student); 11 } 12 13 @Test 14 public void testQueryStudent2() { 15 // 通過id查詢一個學生 16 try { 17 Student student = runner.query("select * from student where id=?", new BeanHandler<Student>(Student.class), 18 2); 19 System.out.println(student); 20 } catch (SQLException e) { 21 e.printStackTrace(); 22 } 23 } 24 25 // 查詢多個學生 26 @Test 27 public void testQueryStudents() { 28 try { 29 List<Student> students = runner.query("select * from student", new BeanListHandler<Student>(Student.class)); 30 for (Student student : students) { 31 System.out.println(student); 32 } 33 } catch (SQLException e) { 34 e.printStackTrace(); 35 } 36 } 37 38 // 查詢聚合函數: 查詢女生的個數 39 @Test 40 public void testQueryGender() { 41 //java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer 42 try { 43 long num = runner.query("select count(*) from student where gender=?", new ScalarHandler<Long>(), "女"); 44 System.out.println(num); 45 } catch (SQLException e) { 46 e.printStackTrace(); 47 } 48 } 49 }