一、先来看看手工创建的方式
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()方法。
区别就是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
上善若水,水利万物而不争。