gpt4 book ai didi

java - Tomcat Web 应用程序中与 Java 和 MySQL 的连接池

转载 作者:可可西里 更新时间:2023-11-01 07:49:23 26 4
gpt4 key购买 nike

我最近编写了一个 Java 网络应用程序并将其部署到服务器,我发现了一个在开发或测试期间没有出现的异常问题。

当用户在这么长时间后登录并去显示数据库中的数据时,页面显示没有记录可看。但是在页面刷新时,根据分页规则显示前 x 条记录。

查看日志,发现:

ERROR|19 09 2009|09 28 54|http-8080-4|myDataSharer.database_access.Database_Metadata_DBA| - Error getting types of columns of tabular Dataset 12

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1956)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2368)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2867)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1616)

等等几百行。

该应用程序目前已为大约 100 名用户设置,但尚未完全使用。它使用 Apache Tomcat servlets/jsps 和 MySQL 数据库之间的连接池,以下代码示例构成了数据库操作的一般安排,其中通常每页有几个:

// Gets a Dataset.
public static Dataset getDataset(int DatasetNo) {
ConnectionPool_DBA pool = ConnectionPool_DBA.getInstance();
Connection connection = pool.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;

String query = ("SELECT * " +
"FROM Dataset " +
"WHERE DatasetNo = ?;");

try {
ps = connection.prepareStatement(query);
ps.setInt(1, DatasetNo);
rs = ps.executeQuery();
if (rs.next()) {
Dataset d = new Dataset();
d.setDatasetNo(rs.getInt("DatasetNo"));
d.setDatasetName(rs.getString("DatasetName"));
...

}

return d;
}
else {
return null;
}
}
catch(Exception ex) {
logger.error("Error getting Dataset " + DatasetNo + "\n", ex);
return null;
}
finally {
DatabaseUtils.closeResultSet(rs);
DatabaseUtils.closePreparedStatement(ps);
pool.freeConnection(connection);
}
}

有没有人能提供解决此问题的方法?

我认为这是由于 MySQL 让连接轮询连接打开长达八小时,但我不确定。

谢谢

马丁·奥谢。


只是为了澄清关于我的连接池方法的一点,我在我的应用程序中使用的不是 Oracle,而是我自己的一个类,如下所示:

package myDataSharer.database_access;

import java.sql.*;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;

public class ConnectionPool_DBA {

static Logger logger = Logger.getLogger(ConnectionPool_DBA.class.getName());

private static ConnectionPool_DBA pool = null;
private static DataSource dataSource = null;


public synchronized static ConnectionPool_DBA getInstance() {
if (pool == null) {
pool = new ConnectionPool_DBA();
}
return pool;
}

private ConnectionPool_DBA() {
try {
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup("java:/comp/env/jdbc/myDataSharer");
}
catch(Exception ex) {
logger.error("Error getting a connection pool's datasource\n", ex);
}
}

public void freeConnection(Connection c) {
try {
c.close();
}
catch (Exception ex) {
logger.error("Error terminating a connection pool connection\n", ex);
}
}

public Connection getConnection() {
try {
return dataSource.getConnection();
}
catch (Exception ex) {
logger.error("Error getting a connection pool connection\n", ex);
return null;
}
}
}

我认为提到 Oracle 是因为我使用了类似的名称。

最佳答案

有一些关于避免这种情况的指示,从其他来源获得,特别是从其他驱动程序和其他应用程序服务器的连接池实现。 JNDI 数据源上的 Tomcat 文档中已经提供了一些信息。

  1. 建立一个清理/收割程序计划,如果池中的连接超过特定时间不活动,将关闭这些连接。将数据库连接保持打开状态 8 小时(MySQL 的默认设置)不是好的做法。在大多数应用程序服务器上,非 Activity 连接超时值是可配置的,通常小于 15 分钟(即连接不能在池中停留超过 15 分钟,除非它们被反复使用)。在 Tomcat 中,当使用 JNDI 数据源时,use the removeAbandoned and removeAbandonedTimeout settings做同样的事情。
  2. 当新连接从连接池返回到应用程序时,确保首先对其进行测试。例如,我所知道的大多数应用程序服务器都可以配置为通过执行“SELECT 1 FROM dual”来测试与 Oracle 数据库的连接。在 Tomcat 中,使用 validationQuery 属性为 MySQL 设置适当的查询——我相信这是“SELECT 1”(不带引号)。之所以设置 validationQuery 属性的值有帮助,是因为如果查询执行失败,连接将从池中删除,并在其位置创建新连接。

就您的应用程序的行为而言,用户可能是第一次看到池向应用程序返回失效连接的结果。第二次,池可能会返回一个可以为应用程序查询提供服务的不同连接。

Tomcat JNDI 数据源基于 Commons DBCP,因此 configuration properties适用于 DBCP 的也适用于 Tomcat。

关于java - Tomcat Web 应用程序中与 Java 和 MySQL 的连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1448974/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com