C3P0作为JDBC一个开源的连接池之一,有自己的很大优点,与DBCP相比,C3P0可以自动回收空闲连接,它实现了数据源和JNDI绑定,并且支持JDBC3规范和JDBC2的标准扩展,甚至Hibernate 和 Spring 都采用它作为JDBC的连接池


前提:

  1. 导入两个Jar包

使用方法一:

不采用封装,直接进行使用,对于一些连接数据库所需要的参数写在了mysql.ini配置文件中,包括driver,url,user,pass 四个配置选项,采用 windows配置文件的格式(键值对)进行配置

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

import java.beans.PropertyVetoException;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import com.mchange.v2.c3p0.ComboPooledDataSource;


public class ToUseC3p0 {


public static void main(String[] args){

/*初始化数据库连接参数*/
Properties props = new Properties();
try {
props.load(new FileInputStream("mysql.ini"));
} catch (IOException e1) {

e1.printStackTrace();
}
String driver = props.getProperty("driver");
String user = props.getProperty("user");
String pass = props.getProperty("pass");
String url = props.getProperty("url");

ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass(driver);
} catch (PropertyVetoException e) {

e.printStackTrace();
}
cpds.setJdbcUrl(url);
cpds.setUser(user);
cpds.setPassword(pass);



/*获得连接,使用连接,然后释放连接*/
Connection conn = null;
try {
conn = cpds.getConnection();
} catch (SQLException e) {

e.printStackTrace();
}finally {
try {
conn.close();

/*这里并没有真正释放连接,而是将连接归还到连接池中*/
} catch (SQLException e) {

e.printStackTrace();
}
}

}

}

使用方法二:

对于方法一的使用,其实有很多弊端,包括每次使用,都需要写一段很长很冗余的代码,不仅仅程序效率低下,后期的维护更是难上加难!方法二,我们初步进行封装,每次都会获得一个连接池

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
public class JdbcUtils {
private static DataSource getDataSource(){
/*初始化数据库连接参数*/
Properties props = new Properties();
try {
props.load(new FileInputStream("mysql.ini"));
} catch (IOException e1) {

e1.printStackTrace();
}
String driver = props.getProperty("driver");
String user = props.getProperty("user");
String pass = props.getProperty("pass");
String url = props.getProperty("url");

ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass(driver);
} catch (PropertyVetoException e) {

e.printStackTrace();
}
cpds.setJdbcUrl(url);
cpds.setUser(user);
cpds.setPassword(pass);

return cpds;
}
}

弊端:

  1. 每次调用这个JdbcUtils类中的方法都会返回一个不同的连接池
  2. 每次调用方法都需要进行初始化连接池的参数,负载大

使用方法三:

对于这个使用C3P0的方法,我们每次都会返回同一个已经配置好的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
    public class JdbcUtils {

/*在类加载的时候便会执行,因此cpds只有一份,不会重复*/
private static ComboPooledDataSource cpds = new ComboPooledDataSource();

private static Properties props = new Properties();
private static String driver;
private static String url;
private static String user;
private static String pass;

static {

/*为了负责,将编译异常转换为运行时异常抛出*/
try {
props.load(new FileInputStream("mysql.ini"));
} catch(Exception e) {
throw new RuntimeException(e);
}

driver = props.getProperty("driver");
url = props.getProperty("url");
user = props.getProperty("user");
pass = props.getProperty("pass");

try {
cpds.setDriverClass(driver);
cpds.setUser(user);
cpds.setJdbcUrl(url);
cpds.setPassword(pass);
} catch (Exception e) {
throw new RuntimeException(e);
}

}

/*为了避免每次调用该方法获得连接池的时候重复设置参数,我们在上面的静态代码块中设置参数*/
public static DataSource getDataSource(){
return cpds;
}

}

注意事项:

  1. 静态代码块中产生的异常我们需要进行转换成运行时异常,并且手动进行抛出
  2. 对于C3P0的使用,我们只需要配置一次,不仅省时,还可以节省空间,不过后期我们会采用XML文件进行配置,这里采用了ini配置文件
  3. 采用JdbcUtils的getDataSource()方法,我们每次都会获得同一个DataSource对象,正符合我们每个项目只需要一个连接池就可以的要求,并且便于管理!