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