线程池与连接池的共同使用

由于请求中的一个事务涉及多个 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();
    }

}