dbcp2连接池获取数据库连接Connection

时间:2022-05-03 08:29:53

一、先来看看手工创建的方式

    public static Connection getConnection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(
                    "jdbc:mysql://127.0.0.1:3306/mytable?useUnicode=true&characterEncoding=utf8", "root",
                    "123456");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

这种直接建立的方式一定要注意:在访问完成后链接的释放。

conn.close();

如果这个时候循环查询一个表100次,你能看到数据库建立了100个链接,如果你释放了的话,100个链接会或快或慢的全部释放掉。

如果数据库访问很频繁的话,好可惜啊,刚建立好一个链接就拆掉了,刚拆完又要新建一个链接……

所以,连接池出来了。较为熟悉的有c3p0、dbcp2等等。

二、通过dbcp2连接池获取Connection

一个较好的初始化配置实例。

 1     // ThreadSafe
 2     private static final ThreadLocal<Connection> connHolder;
 3     private static final BasicDataSource dataSource;
 4     
 5     static {
 6         connHolder = new ThreadLocal<Connection>();
 7         dataSource = new BasicDataSource();
 8         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
 9         dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/mytable");
10         dataSource.setUsername("root");
11         dataSource.setPassword("123456");
12         /// 设置空闲和借用的连接的最大总数量,同时可以激活。
13         dataSource.setMaxTotal(60);
14         // 设置初始大小
15         dataSource.setInitialSize(5);
16         // 最小空闲连接
17         dataSource.setMinIdle(8);
18         // 最大空闲连接
19         dataSource.setMaxIdle(16);
20         // 超时等待时间毫秒
21         dataSource.setMaxWaitMillis(2 * 10000);
22         // 只会发现当前连接失效,再创建一个连接供当前查询使用
23         dataSource.setTestOnBorrow(true);
24         // removeAbandonedTimeout :超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180)
25         dataSource.setRemoveAbandonedTimeout(180);
26         // removeAbandoned :超过removeAbandonedTimeout时间后,是否进
27         // 行没用连接(废弃)的回收(默认为false,调整为true)
28         // DATA_SOURCE.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance);
29         dataSource.setRemoveAbandonedOnBorrow(true);
30         // testWhileIdle
31         dataSource.setTestOnReturn(true);
32         // testOnReturn
33         dataSource.setTestOnReturn(true);
34         // setRemoveAbandonedOnMaintenance
35         dataSource.setRemoveAbandonedOnMaintenance(true);
36         // 记录日志
37         dataSource.setLogAbandoned(true);
38         dataSource.setDefaultAutoCommit(true);
39 
40     }
41 
42     public static Connection getConnection() {
43         Connection conn = connHolder.get();
44         if (conn == null) {
45             try {
46                 conn = dataSource.getConnection();
47                 System.out.println("get connection success");
48             } catch (SQLException e) {
49                 System.out.println("get connection failure:" + e);
50             } finally {
51                 connHolder.set(conn);
52             }
53         }
54         return conn;
55     }
56 
57     public static void closeConnection() {
58         Connection conn = connHolder.get();
59         if (conn != null) {
60             try {
61                 conn.close();
62                 System.out.println("close connection success");
63             } catch (SQLException e) {
64                 System.out.println("close connection failure:" + e);
65                 throw new RuntimeException(e);
66             } finally {
67                 connHolder.remove();
68             }
69         }
70     }

实际使用的时候,释放conn链接的方法可以直接调用conn.close()方法,也可以使用closeConnection()方法。

区别就是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。