Apache DBCP连接池Java示例

时间:2020-01-09 10:35:21  来源:igfitidea点击:

在本文中,我们将介绍如何使用Apache DBCP在应用程序中配置连接池。

为什么需要连接池

如果每次用户连接到数据库并随后关闭数据库连接时都创建了数据库连接,则将浪费大量时间来创建连接对象本身来执行数据库事务,这可能需要几毫秒的时间。与其为每个用户打开连接,不如创建一个在用户之间共享的连接池,效率更高。

每当用户必须连接到数据库并且完成连接返回到池以供另一个用户使用时,用户都可以从连接池中检索空闲连接对象。我们还可以对池中的连接数施加上限,在这种情况下,如果达到了池的最大打开连接限制,则当其他用户释放该连接时,会将对该连接的任何其他请求排队以获取连接。

Maven对Apache DBCP的依赖

如果我们使用的是Maven,则可以在pom.xml中添加以下依赖项

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-dbcp2</artifactId>
  <version>2.8.0</version>
</dependency>

我们也可以直接从以下位置下载jar,然后将其放入应用程序的类路径中。

https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

Apache DBCP连接池Java示例

在示例数据库中使用的是MySQL,它连接到theitroad架构,表是EMPLOYEE,其列为id,FIRST_NAME,LAST_NAME和DEPARTMENT。

Apache DBCP提供了一个BasicDataSource类,该类创建一个PoolingDataSource。使用BasicDataSource创建DataSource实例并配置连接池的步骤如下:

1.创建BasicDataSource类的对象。
2.设置与数据库相关的配置,例如驱动程序类,URL,用户名和密码。
3.从以下选项中指定所需的与连接池相关的配置:

  • initialSize –启动池时创建的初始连接数。默认值为0。
  • maxTotal –可以同时从该池中分配的活动连接的最大数目,或者为无限制的负数。默认值为8.
  • maxIdle –池中可以保持空闲的最大连接数。默认值为8.
  • minIdle –池中可以保持空闲的最小连接数。默认值为0。
  • maxWaitMillis –在引发异常之前,池将等待(没有可用连接时)连接返回的最大毫秒数。默认等待时间是无限的。

以下类用于创建BasicDataSource。

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;

public class DSCreator {
  private static BasicDataSource basicDS;
  static {
    try {
      basicDS = new BasicDataSource();
      Properties properties = new Properties();
      // Loading properties file from classpath
      InputStream inputStream = DSCreator.class
                                         .getClassLoader()
                                         .getResourceAsStream("db.properties");
      if(inputStream == null){
        throw new IOException("File not found");
      }
      properties.load(inputStream);	
      basicDS.setDriverClassName(properties.getProperty("DB.DRIVER_CLASS"));
      basicDS.setUrl(properties.getProperty("DB.DB_URL"));
      basicDS.setUsername(properties.getProperty("DB.DB_USER"));
      basicDS.setPassword(properties.getProperty("DB.DB_PASSWORD"));
      //The initial number of connections that are created when the pool is started.
      basicDS.setInitialSize(Integer.parseInt(properties.getProperty("DB.INITIAL_POOL_SIZE")));
      //The maximum number of active connections that can be allocated from this pool at the same time
      basicDS.setMaxTotal(Integer.parseInt(properties.getProperty("DB.MAX_POOL_SIZE")));
    }catch(IOException e) {
      e.printStackTrace();
    }
  }
  public static DataSource getDataSource() {
    return basicDS;
  } 
}

程序用来读取数据库属性的属性文件(db.properties)确保此属性文件在类路径中。

DB.DRIVER_CLASS=com.mysql.cj.jdbc.Driver
DB.DB_URL=jdbc:mysql://localhost:3306/theitroad
DB.DB_USER=root
DB.DB_PASSWORD=admin
DB.INITIAL_POOL_SIZE=5
DB.MAX_POOL_SIZE=5

测试类,该类使用返回的DataSource对象创建连接并查询数据库。

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;

public class DSDemo {
  public static void main(String[] args) {
    DSDemo dsDemo = new DSDemo();
    dsDemo.displayEmployeeById(16);
  }
  private void displayEmployeeById(int id){
    Connection connection = null; 
    String selectSQL = "SELECT * FROM EMPLOYEE WHERE id = ?";
    PreparedStatement prepStmt = null;
    try {
      DataSource ds = DSCreator.getDataSource();
      connection = ds.getConnection();
      prepStmt = connection.prepareStatement(selectSQL);
      prepStmt.setInt(1, id);
      ResultSet rs = prepStmt.executeQuery();
      while(rs.next()){
        System.out.println("id: " + rs.getInt("id"));
        System.out.println("First Name: " + rs.getString("FIRST_NAME"));
        System.out.println("Last Name: " + rs.getString("LAST_NAME"));
        System.out.println("Department: " + rs.getString("DEPARTMENT"));
      }
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}