2010-11-17 183 views
9

我有一个使用JDBC连接到MySQL的应用程序。在某些情况下,JDBC连接处于空闲状态几个小时(甚至可能是几天),并且它失去了与MySQL的连接,然后除非它试图执行查询。什么是最好的解决方案?使用JDBC连接到MySQL

回答

15

保持连接打开的时间是一个不好的做法。数据库在打开很长一段时间后会强制关闭。您应该编写JDBC代码,以便始终关闭与您已获取它们的块相同的finally块中的连接(以及语句和结果集),以防止资源泄漏。

但是,获取每个打嗝的连接确实是一项相当昂贵的任务,因此您希望使用连接池的。体面连接池将自行管理打开,测试,重用和关闭连接。然而,这并不意味着你可以改变你的JDBC代码,永不关闭它们。您仍然需要关闭它们,因为这实际上会将底层连接释放回池以备将来重用。

有几个连接池,像Apache DBCP这是单线程,因此在性能差,C3P0这是多线程和性能更好,并为Tomcat JDBC您使用Tomcat和不希望使用内置的DBCP的情况下由于表现不佳。

可以通过编程创建连接池,在这里与C3P0一个例子:

ComboPooledDataSource dataSource = new ComboPooledDataSource(); 
dataSource.setDriverClass("com.mysql.jdbc.Driver"); 
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dbname"); 
dataSource.setUser("username"); 
dataSource.setPassword("password"); 

在应用程序的启动做一次,然后就可以按如下方式使用它:

Connection connection = null; 
// ... 

try { 
    connection = dataSource.getConnection(); 
    // ... 
} finally { 
    // ... 
    if (connection != null) try { connection.close(); } catch (SQLException ignore) {} 
} 

当你运行在像servlet容器(例如Tomcat)的支持JNDI的容器中,那么您也可以声明它为java.sql.DataSource(Tomcat特定手册here)。然后它将使用servletcontainer提供的连接池设施。然后您可以按如下方式获取数据源:

DataSource dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/YourDataSourceName"); 
+0

为什么不把连接保持为类成员,检查它是否在计划使用时关闭,并在关闭时启动新连接?除了保持一段时间的记忆之外,这会有什么问题呢? – 2015-10-06 06:32:09

+2

@EB:这是丝毫不安全的。相关:http://stackoverflow.com/q/9428573您应该为每个线程和事务使用一个完全独立的连接。他们可以保持开放并在完成线程本地事务作业后重用,但这已经正是连接池的功能。连接池并没有在物理上关闭连接,它只是保持打开并在释放之前对其进行测试(正如本文中已经回答的那样) – BalusC 2015-10-06 06:33:36

4

有库,如Apache's DBCP可以做连接池。其中一部分是它们可以设置为在您使用它时自动测试连接(例如“SELECT NOW()FROM DUAL”或其他无害),并在必要时自动重新建立连接,从而允许您应用程序假装连接是永久的。

+0

这是要走的路。您甚至可以在将连接返回给客户端之前将其设置为执行一个虚拟SELECT,以便您知道它会起作用。 – 2010-11-17 22:18:43