DBCP(DataBase Connection Pool),数据库连接池。用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

连接池也是使用四大连接参数来完成创建连接对象! 即:driverClass、url、username和password。

自定义JDBC连接池

实现的接口

连接池必须实现:javax.sql.DataSource接口!
连接池返回的Connection对象,它的close()方法与众不同!调用它的close()不是关闭,而是把连接归还给池!代表该链接不被占用了。

JDBC数据库连接池接口(DataSource)

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

自定义连接池代码部分

  • MyJDBCDataSource.java 实现 DataSource接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package com.hyf.jdbc.util;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

public class MyJDBCDataSource implements DataSource {

private LinkedList<Connection> pool = new LinkedList<Connection>();

public MyJDBCDataSource() {
// 初始化连接池中的连接,一次存放5个
addConnction();
}

@Override
public Connection getConnection() throws SQLException {
// TODO Auto-generated method stub
// 如果池子里边为空,那么就添加新的Connection连接对象
if (pool.size() == 0) {
addConnction();
}
// 最终返回的是池子里边第一个Connection对象
return pool.removeFirst();
}

/**
* 归还连接对象到连接池中去
*/

public void close(Connection con){
if (con==null) return;
pool.add(con);
}

/**
* 往连接池中添加连接对象
*/
private void addConnction() {
for (int i = 0; i < 5; i++) {
pool.add(JDBCUtilsV2.getConnection());
}
}

@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}

@Override
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub

}

@Override
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub

}

@Override
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}

@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
// TODO Auto-generated method stub
return null;
}

}
  • 使用测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MyJDBCDataSource dataSource = new MyJDBCDataSource();
Connection con = null;
try {
con = dataSource.getConnection();
String sql = "insert into user values(null,?,?);";
PreparedStatement statement = con.prepareStatement(sql);
statement.setString(1, "吕布");
statement.setString(2, "貂蝉");
int rows = statement.executeUpdate();
if (rows>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
dataSource.close(con);
}

自定义连接池改造(connection工作完成之后将对象添加到连接池中的步骤在connection对象的close方法中实现)

  • 自定义Connection类,主要重写close方法和prepareStatement方法,目的,在close方法中,将该对象添加到pool中,preparestatement方法是为了执行sql语句
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    private LinkedList<Connection> pool;
    private Connection con;
    // 重写构造方法,传过来Connection对象和pool
    public MyConnection(Connection con,LinkedList<Connection> pool) {
    this.con = con;
    this.pool = pool;
    }
    /**
    * 必须重写此方法,用完后将connection对象返还给pool
    */
    @Override
    public void close() throws SQLException {
    // TODO Auto-generated method stub
    pool.add(con);
    }

    /**
    * 必须重写此方法,执行sql语句
    */
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
    // TODO Auto-generated method stub
    return con.prepareStatement(sql);
    }
  • 自定义连接池对象,实现DataSource接口,将上面自定义的MyJDBCDataSource类中的addConnction()方法改造为
    1
    2
    3
    4
    5
    6
    7
    private void addConnction() {
    for (int i = 0; i < 5; i++) {
    Connection con = JDBCUtilsV2.getConnection();
    MyConnection myConnection = new MyConnection(con, pool);
    pool.add(myConnection);
    }
    }
  • 使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 此为改造后的DataSource实例
    MyJDBCDataSource2 dataSource = new MyJDBCDataSource2();
    Connection con = null;
    PreparedStatement statement = null;
    try {
    con = dataSource.getConnection();
    String sql = "insert into user values(null,?,?);";
    statement = con.prepareStatement(sql);
    statement.setString(1, "吕布1");
    statement.setString(2, "貂蝉1");
    int rows = statement.executeUpdate();
    if (rows>0) {
    System.out.println("添加成功");
    }else {
    System.out.println("添加失败");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally {
    // 关闭会调用重写的MyConnection中的close方法
    JDBCUtilsV2.close(null, statement, con);
    }

    C3P0连接池

C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用第三方工具需要导入jar包,c3p0使用时还需要添加配置文件c3p0-config.xml,必须使用此命名!

导入jar包

jar包下载地址:链接:http://pan.baidu.com/s/1hrNsLW4 密码:99v4

配置文件

  • 配置文件名称:c3p0-config.xml固定

  • 配置文件位置:src(类路径)

  • 配置项

    Paste_Image.png

    Paste_Image.png

  • 配置文件c3p0-config.xml内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    <default-config>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql:///web1024</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">20</property>
    </default-config>

    <named-config name="hyf">
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql:///web08</property>
    <property name="user">root</property>
    <property name="password">root</property>
    </named-config>
    </c3p0-config>

    使用

    基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // 自动加载配置文件 并读取配置参数中的内容
    // 加载默认的配置
    DataSource dataSource = new ComboPooledDataSource();
    // 加载有名称的配置
    //DataSource dataSource = new ComboPooledDataSource("hyf");
    Connection con = null;
    PreparedStatement statement = null;
    try {
    con = dataSource.getConnection();
    String sql = "insert into user values(null,?,?);";
    statement = con.prepareStatement(sql);
    statement.setString(1, "吕布2");
    statement.setString(2, "貂蝉2");
    int rows = statement.executeUpdate();
    if (rows>0) {
    System.out.println("添加成功");
    }else {
    System.out.println("添加失败");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally {
    JDBCUtilsV2.close(null, statement, con);
    }

    改造使用

  1. C3P0Utils工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class C3P0Utils {
    private static DataSource dataSource = new ComboPooledDataSource();
    public static DataSource getDataSource(){
    return dataSource;
    }

    public static Connection getConnection(){
    try {
    return dataSource.getConnection();
    } catch (Exception e) {
    // TODO Auto-generated catch block
    //e.printStackTrace();
    throw new RuntimeException(e);
    }
    }
    }
  2. 使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Connection con = null;
    PreparedStatement statement = null;
    try {
    con = C3P0Utils.getConnection();
    String sql = "insert into user values(null,?,?);";
    statement = con.prepareStatement(sql);
    statement.setString(1, "吕布3");
    statement.setString(2, "貂蝉3");
    int rows = statement.executeUpdate();
    if (rows>0) {
    System.out.println("添加成功");
    }else {
    System.out.println("添加失败");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally {
    JDBCUtilsV2.close(null, statement, con);
    }

DBCP连接池

DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

导入jar包

jar包下载地址:链接:http://pan.baidu.com/s/1boMNbAn 密码:eea1

配置项

  1. 配置文件名称*.properties

  2. 配置文件位置,建议存放在src文件夹下

  3. 配置文件内容,配置项如下图:

    Paste_Image.png
    Paste_Image.png

配置详情

1
2
3
4
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.0.111:3306/web1024
username=root
password=root

代码

  1. DBCPUtils工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.hyf.dbcp;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCPUtils {
private static DataSource dataSource;

static {
InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
try {
properties.load(is);
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static DataSource getDataSource(){
return dataSource;
}

public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Connection con;
PreparedStatement statement;
try {
con = DBCPUtils.getConnection();
String sql = "insert into user values(null,?,?);";
statement = con.prepareStatement(sql);
statement.setString(1, "吕布4");
statement.setString(2, "貂蝉4");
int rows = statement.executeUpdate();
if (rows>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

相关问题

  • 应用程序中,使用完一个数据库连接后,DBCP连接池如何管理该连接。

    1. 应用程序中主动关闭该连接。如:con.close()。这种情况并不是手动将该连接关闭,而是将该连接交回给DBCP连接池,由连接池管理该连接。即用完连接后显示的将数据库连接提交至DBCP连接池。

    2. 应用程序中不关闭该连接。这种情况DBCP配置文件db.properties中的配置项(注意jar包版本,低版本中使用removeAbandoned=true配置项) 

      1
      2
      3
      removeAbandonedOnMaintenance=true
      removeAbandonedOnBorrow=true
      removeAbandonedTimeout=1

      会起作用,removeAbandonedOnMaintenance=trueremoveAbandonedOnBorrow=true表示DBCP连接池自动管理应程序中使用完毕的连接,removeAbandonedTimeout=1表示一个连接在程序中使用完毕后,若在1秒之内没有再次使用,则DBCP连接池回收该连接(通常removeAbandonedTimeout不会配置1,此处为了测试使用)。



后台     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!