線程池與連接池的共同使用
由於請求中的一個事務涉及多個 DAO 操作,而這些 DAO 中的 Connection 都能從連接池中獲得,如果是從連接池獲得的話,兩個 DAO 就用到了兩個Connection,這樣的話是沒有辦法完成一個事務的。DAO 中的 Connection 如果是從 ThreadLocal 中獲得 Connection 的話那么這些 DAO 就會被納入到同一個 Connection 之下。當然了,這樣的話,DAO 中就不能把 Connection 給關了,關掉的話,下一個使用者就不能用了。
線程池與連接池結合的實例
package connection; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; public class ConnectionPool { //創建數據源 private static BasicDataSource dataSource = new BasicDataSource(); public ConnectionPool(){ //為數據源填寫必填屬性 dataSource.setUsername("root"); dataSource.setPassword("123456"); dataSource.setUrl("jdbc:mysql://localhost:3306/tan"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); //指定數據庫連接池中初始化連接數的個數 dataSource.setInitialSize(5); //指定最大的連接數:同一時刻同時向數據庫申請的連接數 //最大空閑數,放洪峰過后,連接池中的連接過多, dataSource.setMaxActive(15); //指定最小連接數:數據庫空閑狀態下所需要保留的最小連接數 //防止當洪峰到來時,再次申請連接引起的性能開銷; dataSource.setMinIdle(10); //最長等待時間:等待數據庫連接的最長時間,單位為毫秒,超出將拋出異常 dataSource.setMaxWait(1000*5); } public Connection getConnection() throws Exception{ return dataSource.getConnection(); } } package StatementTest; import java.sql.Connection; import java.sql.SQLException; import connection.ConnectionPool; import connection.ConnectionProvider; public class PreparedStatementTest { /*創建連接池+DataSource操作*/ private static ConnectionPool connectionPool; /*創建線程池+ThreadLocal<T>操作*/ //創建線程池 private static ThreadLocal<Connection> conWrapper = new ThreadLocal<Connection>(); //打開連接 private Connection getConnection() throws Exception{ Connection con = connectionPool.getConnection(); if(con != null || !con.isClosed()){ return con; } //從線程池中獲取數據庫連接 con = connectionPool.getConnection(); if(con == null){ throw new SQLException("無法獲取數據庫連接"); } //對新創建的數據庫連接放到線程池中 conWrapper.set(con); return con; } //關閉連接 private void closeConnection() throws SQLException{ //從線程池中獲取連接池 Connection con = conWrapper.get(); if(con != null){ con.close(); } conWrapper.remove(); } }