Java操作數據庫——使用連接池連接數據庫
摘要:本文主要學習了如何使用JDBC連接池連接數據庫。
傳統方式和連接池方式
傳統方式的步驟
使用傳統方式在Java中使用JDBC連接數據庫,完成一次數據庫的操作,一般有以下幾個步驟:
加載驅動。
建立連接。
執行SQL語句。
釋放連接。
傳統方式的弊端
每一次對數據庫的操作都要建立一次連接,並且會將得到的Connection對象加載到內存中,導致消耗了大量的內存和時間。如果短時間有很多需要進行建立連接的操作,會導致占用很多系統資源,甚至會導致服務器崩潰。
同建立連接相對應,每次使用都需要手動釋放連接,如果忘記釋放連接或者程序出現異常未能成功釋放,會導致內存泄露。
此外,傳統方式並不能控制連接的數量,如果連接的人數過多,會導致無限制的創建連接對象,導致內存開銷過大,服務器崩潰。
連接池的步驟
創建連接池並配置連接屬性。
使用連接池獲取連接。
連接池的優勢
每次需要連接數據庫時,不需要建立連接,而是通過連接池獲取,由連接池提供連接。
在使用完連接后,不需要手動釋放連接,而是交由連接池釋放連接。
可以通過連接池控制連接的數量,在連接池里的連接可多次重復使用,避免了無限制創建連接的問題。
使用連接池
使用C3P0連接池
C3P0是一個開放源代碼的JDBC連接池,它在lib目錄中與Hibernate一起發布,包括實現了數據源和JNDI綁定,支持JDBC3規范和JDBC2的標准擴展。目前使用它的開源項目有Hibernate,Spring等。
導入jar包:
1 c3p0-0.9.5.2.jar
在當前項目的代碼根目錄 src 下新建名為 c3p0-config.xml 的配置文件,注意文件名稱不可改變,內容如下:
1 <c3p0-config> 2 <!-- 連接名稱 --> 3 <named-config name="mysql"> 4 <!-- 接數據庫的驅動類名 --> 5 <property name="driverClass">com.mysql.jdbc.Driver</property> 6 <!-- 連接屬性 --> 7 <property name="jdbcUrl">jdbc:mysql://192.168.35.128:3306/demo</property> 8 <property name="user">root</property> 9 <property name="password">123456</property> 10 <!-- 當連接池用完時等待獲取新連接的時間,超時后將拋出SQLException,單位毫秒,如設為0則無限期等待。默認為0。 --> 11 <property name="checkoutTimeout">5000</property> 12 <!-- 當連接用盡后,一次獲取的連接個數 --> 13 <property name="acquireIncrement">2</property> 14 <!-- 初始連接數 --> 15 <property name="initialPoolSize">1</property> 16 <!-- 最小連接數 --> 17 <property name="minPoolSize">3</property> 18 <!-- 最大連接數 --> 19 <property name="maxPoolSize">5</property> 20 </named-config> 21 </c3p0-config>
程序代碼:
1 public class TestDataPool { 2 // 根據配置文件里的名稱創建連接池 3 public static ComboPooledDataSource cpds = new ComboPooledDataSource("mysql"); 4 5 /** 6 * 主程序 7 */ 8 public static void main(String[] args) { 9 // 模擬多次對數據庫的查詢操作 10 for (int i = 0; i < 6; i++) { 11 new Thread(new Runnable() { 12 @Override 13 public void run() { 14 select(); 15 } 16 }, "線程" + i).start(); 17 } 18 } 19 20 /** 21 * 查詢程序 22 */ 23 public static void select() { 24 Connection conn = null; 25 PreparedStatement pstmt = null; 26 ResultSet rs = null; 27 // 獲取連接並執行SQL 28 try { 29 conn = cpds.getConnection(); 30 pstmt = conn.prepareStatement("select * from student where id = 906"); 31 rs = pstmt.executeQuery(); 32 while (rs.next()) { 33 System.out.println(Thread.currentThread().getName() + "\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString("address")); 34 } 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } finally { 38 // 釋放資源 39 try { 40 rs.close(); 41 } catch (SQLException e) { 42 e.printStackTrace(); 43 } 44 try { 45 pstmt.close(); 46 } catch (SQLException e) { 47 e.printStackTrace(); 48 } 49 try { 50 conn.close(); 51 } catch (SQLException e) { 52 e.printStackTrace(); 53 } 54 } 55 } 56 }
使用DBCP連接池
DBCP是Apache上的一個Java連接池項目,是一個依賴Jakarta項目commons-pool對象池機制的數據庫連接池。DBCP可以直接的在應用程序中使用,Tomcat的數據源使用的就是DBCP。
導入jar包:
1 commons-dbcp-1.4.jar2 commons-pool-1.5.5.jar
在當前項目的代碼根目錄 src 下新建名為 dbcp.properties 的配置文件,文件名需要同代碼中引用的文件名一致,內容如下:
1 # 接數據庫的驅動類名 2 driverClassName=com.mysql.jdbc.Driver 3 # 連接屬性 4 url=jdbc:mysql://192.168.35.128:3306/demo 5 username=root 6 password=123456 7 # 初始化連接數 8 initialSize=10 9 # 最大連接數 10 maxActive=15
程序代碼:
1 public class TestDBCP { 2 // 根據配置文件里的名稱創建連接池 3 private static DataSource source = null; 4 static { 5 Properties pros = new Properties(); 6 InputStream is = TestDBCP.class.getClassLoader().getResourceAsStream("dbcp.properties"); 7 try { 8 pros.load(is); 9 source = BasicDataSourceFactory.createDataSource(pros); 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } 13 } 14 15 /** 16 * 主程序 17 */ 18 public static void main(String[] args) { 19 // 模擬多次對數據庫的查詢操作 20 for (int i = 0; i < 6; i++) { 21 new Thread(new Runnable() { 22 @Override 23 public void run() { 24 select(); 25 } 26 }, "線程" + i).start(); 27 } 28 } 29 30 /** 31 * 查詢程序 32 */ 33 public static void select() { 34 Connection conn = null; 35 PreparedStatement pstmt = null; 36 ResultSet rs = null; 37 // 獲取連接並執行SQL 38 try { 39 conn = source.getConnection(); 40 pstmt = conn.prepareStatement("select * from student where id = 906"); 41 rs = pstmt.executeQuery(); 42 while (rs.next()) { 43 System.out.println(Thread.currentThread().getName() + "\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString("address")); 44 } 45 } catch (Exception e) { 46 e.printStackTrace(); 47 } finally { 48 // 釋放資源 49 try { 50 rs.close(); 51 } catch (SQLException e) { 52 e.printStackTrace(); 53 } 54 try { 55 pstmt.close(); 56 } catch (SQLException e) { 57 e.printStackTrace(); 58 } 59 try { 60 conn.close(); 61 } catch (SQLException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 }
使用Druid連接池
Druid是阿里巴巴出品的數據源,而且是淘寶和支付寶專用數據庫連接池,但它不僅僅是一個數據庫連接池,它還包含一個ProxyDriver,一系列內置的JDBC組件庫,一個SQL Parser。
導入jar包:
1 druid-1.0.9.jar
在當前項目的代碼根目錄 src 下新建名為 druid.properties 的配置文件,文件名需要同代碼中引用的文件名一致,內容如下:
1 # 接數據庫的驅動類名 2 driverClassName=com.mysql.jdbc.Driver 3 # 連接屬性 4 url=jdbc:mysql://192.168.35.128:3306/demo 5 username=root 6 password=123456 7 # 最大連接數 8 maxActive=15 9 # 最長等待時間 10 maxWait=3000 11 # 配置初始化連接數 12 initialSize=1 13 # 配置最大活動連接數 14 maxActive=10
程序代碼:
1 public class TestDruid { 2 // 根據配置文件里的名稱創建連接池 3 private static DataSource source = null; 4 static { 5 Properties pros = new Properties(); 6 InputStream is = TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"); 7 try { 8 pros.load(is); 9 source = DruidDataSourceFactory.createDataSource(pros); 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } 13 } 14 15 /** 16 * 主程序 17 */ 18 public static void main(String[] args) { 19 // 模擬多次對數據庫的查詢操作 20 for (int i = 0; i < 6; i++) { 21 new Thread(new Runnable() { 22 @Override 23 public void run() { 24 select(); 25 } 26 }, "線程" + i).start(); 27 } 28 } 29 30 /** 31 * 查詢程序 32 */ 33 public static void select() { 34 Connection conn = null; 35 PreparedStatement pstmt = null; 36 ResultSet rs = null; 37 // 獲取連接並執行SQL 38 try { 39 conn = source.getConnection(); 40 pstmt = conn.prepareStatement("select * from student where id = 906"); 41 rs = pstmt.executeQuery(); 42 while (rs.next()) { 43 System.out.println(Thread.currentThread().getName() + "\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString("address")); 44 } 45 } catch (Exception e) { 46 e.printStackTrace(); 47 } finally { 48 // 釋放資源 49 try { 50 rs.close(); 51 } catch (SQLException e) { 52 e.printStackTrace(); 53 } 54 try { 55 pstmt.close(); 56 } catch (SQLException e) { 57 e.printStackTrace(); 58 } 59 try { 60 conn.close(); 61 } catch (SQLException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 }
