C3P0连接池

 在Java开发中,使用JDBC操作数据库的四个步骤如下:

      ①加载数据库驱动程序(Class.forName("数据库驱动类");)
      ②连接数据库(Connection con  = DriverManager.getConnection();)
      ③操作数据库(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
      ④关闭数据库,释放连接(con.close();)
  也就是说,所有的用户都需要经过此四步进行操作,但是这四步之中有三步(①加载数据库驱动程序、②连接数据库、④关闭数据库,释放连接)对所有人都是一样的,而所有人只有在操作数据库上是不一样,那么这就造成了性能的损耗。
  那么最好的做法是,准备出一个空间,此空间里专门保存着全部的数据库连接,以后用户用数据库操作的时候不用再重新加载驱动、连接数据库之类的,而直接从此空间中取走连接,关闭的时候直接把连接放回到此空间之中。
      那么此空间就可以称为连接池(保存所有的数据库连接)

 

C3P0相关认识

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目Hibernate,Spring等。

 

什么是连接池:

     连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用;简单理解为,当一辆汽车搬运东西,如果使用jdbc连接,(jdbc连接:与数据库建立连接、发送操作数据库的语句并处理结果)那么每一次都要去打开数据库,获得连接,关闭数据库。假设汽车搬运的东西是连接,那么我可不可以每一次将连接搬运多个呢?而不是jdbc那样,一次只搬运一个连接,然后就把汽车扔掉?这时候,使用连接池。

 C3P0连接池

 

 

主流连接池:
DBCP C3P0 阿里巴巴的druid

原理:

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

 

为什么要用到连接池

     数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。连接池主要由三部分组成:连接池的建立、连接池中连接的使用管理、连接池的关闭。

数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:

  1. 最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
  2. 最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
  3. 如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放

使用c3p0需要导包:C3P0.jar

写一个工具类:
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
99
100
101
102
103
104
105
106
public class DBUtils {  
       
    private static String url = null;  
       
    private static String username = null;  
       
    private static String pwd = null;  
       
    private static DataSource ds_pooled;  
    /**  
     *  加载数据库连接的配置文件和驱动 
     */  
    static{  
        FileInputStream fis = null;  
           
        Properties env = new Properties();  
        try {  
            fis = new FileInputStream("dbconfig.properties");  
            //加载属性文件中的数据库配置信息  
            //以=左边作为key值,右边作为value值  
            env.load(fis);   
               
            //1. 加载驱动类  
            Class.forName(env.getProperty("jdbc.driver"));  
               
            url = env.getProperty("jdbc.url");  
            username = env.getProperty("jdbc.username");  
            pwd = env.getProperty("jdbc.pwd");  
               
            //设置连接数据库的配置信息  
            DataSource ds_unpooled = DataSources  
                    .unpooledDataSource(url, username, pwd);  
               
            Map<String, Object> pool_conf = new HashMap<String, Object>();  
            //设置最大连接数  
            pool_conf.put("maxPoolSize"10);  
            ds_pooled = DataSources.pooledDataSource(ds_unpooled,  
                    pool_conf);  
        catch (FileNotFoundException e) {  
            e.printStackTrace();  
        catch (IOException e) {  
            e.printStackTrace();  
        catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
       
    /** 
     *  获取连接对象 
     */  
    public static Connection getConnection() throws SQLException {  
        // 2. 设置连接的url,username,pwd  
//      return DriverManager.getConnection(url, username, pwd);  
        return ds_pooled.getConnection();  
    }  
       
    /** 
     * 释放连接池资源 
     */  
    public static void clearup(){  
        if(ds_pooled != null){  
            try {  
                DataSources.destroy(ds_pooled);  
            catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
       
       
    /** 
     * 资源关闭 
     *  
     * @param rs 
     * @param stmt 
     * @param conn 
     */  
    public static void close(ResultSet rs, Statement stmt  
            , Connection conn) {  
        if (rs != null) {  
            try {  
                rs.close();  
            catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
   
        if (stmt != null) {  
            try {  
                stmt.close();  
            catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
   
        if (conn != null) {  
            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
public class TestMySQLConnection {  
    private static Integer counter = 0;  
   
    public static void main(String[] args){  
        for (int i = 1; i <= 20; i++) {  
            new Thread(new Runnable() {  
                public void run() {  
                    Connection conn = null;  
                    try {  
                        conn = DBUtils.getConnection();  
                        synchronized (counter) {  
                            System.out.print(Thread.currentThread().getName());  
                            System.out.print("    counter = " + counter++  
                                    "  conn = " + conn);  
                            System.out.println();  
                               
                            conn.prepareStatement("select * from t_user");  
                               
                            conn.close();  
                        }  
                    catch (SQLException e) {  
                        e.printStackTrace();  
                    }    
                }  
            }).start();  
        }  
    }  
}