线程池与连接池的共同使用
由于请求中的一个事务涉及多个 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(); } }