我有一个应用程序,我正在连接到MySQL数据库。它在半夜失去连接,然后喷出null
个连接,并且JDBC在X秒内没有收到消息。
在我做任何需要与SQL服务器通信的事情之前,我会调用getConnection()
。
这是我的getConnection()
方法:
private Connection getConnection() {
try {
if (connection != null) {
if (connection.isClosed() || !connection.isValid(10000)) {
this.initializeRamsesConnection();
}
} else {
this.initializeRamsesConnection();
}
} catch (Exception e) {
debug("Connection failed: " + e);
}
return connection;
}
在initializeRamsesConnection()
方法中,我将密码等信息放入字符串中,然后以标准JDBC方式创建连接。
然后我称之为这个方法:
private Connection getConnectionFromConnectionString() {
Connection con = null;
String driver = "com.mysql.jdbc.Driver";
try {
Class.forName(driver);//jdbc sorcery
//if there is no connection string
if (getConnectionString() == null) {
HMIDatabaseAdapter.debug("No connection string");
}
//makes a string out of the values of db/host
String str = getConnectionString();
//if there is no driver
if (driver == null) {
debug("" + ": " + "No driver");
}
//Tries to make a connection from the connection string, username, and the password.
con = DriverManager.getConnection(str, username, password);
//if for some reason the connection is null
if (con == null) {
HMIDatabaseAdapter.debug("CONNECTION IS NULL, WHAT?");
}
} catch (Exception ex) {
HMIDatabaseAdapter.debug("getConnection() " + ex);
}
return con;
}
我可以在这两种方法中改变什么来容纳失去联系?
答案 0 :(得分:14)
这不是检索连接的正确方法。您正在检索连接并将其指定为类的实例(或更糟,静态)变量。基本上,您将永远保持连接打开,并为所有查询重用单个连接。如果查询由不同的线程执行,这可能最终导致灾难。此外,当它保持打开状态太长时间时,DB会收回它,因为它假定它已经死亡/泄漏。
您应该在尽可能短的范围中获取并关闭连接。即在与执行查询的块try
块相同的块中。像这样:
public Entity find(Long id) throws SQLException {
Entity entity = null;
try (
Connection connection = dataSource.getConnection(); // This should return a NEW connection!
PreparedStatement statement = connection.prepareStatement(SQL_FIND);
) {
statement.setLong(1, id);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
entity = new Entity(
resultSet.getLong("id"),
resultSet.getString("name"),
resultSet.getInt("value")
);
}
}
}
return entity;
}
如果您担心连接性能并希望重用连接,那么您应该使用连接池。你可以养一个,但我强烈反对这一点,因为你似乎对这些东西很新。只需使用现有的连接池,例如BoneCP,C3P0或DBCP。请注意,您应该不更改JDBC惯用法,如上例所示。您仍然需要在尽可能短的范围内获取和关闭连接。连接池本身会担心实际重用,测试和/或关闭连接。
答案 1 :(得分:0)
代码中的哪个位置是丢失连接的错误?这可能是最好的起点。
脱离我的头脑(我可能错了),JDBC连接只会在实际致命错误时关闭,所以在你尝试做某事之前你不会知道它们已经失败了。
我过去所做的是在失败时使连接无效并定期重试。
答案 2 :(得分:0)
也许这就是你要找的东西: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html
对于java,请参阅autoReconnect: http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html