当我的应用程序失去连接时,我应该如何恢复它?

dav*_*nes 4 java database-connection jdbc

我有一个应用程序,我正在连接到MySQL数据库.它在半夜失去连接,然后喷出null连接,JDBC在X秒内没有收到消息.

getConnection()在我做任何需要与SQL服务器通信的事情之前,我打电话.

这是我的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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

我可以在这些方法中更改哪些内容以适应丢失连接?

Bal*_*usC 15

这不是检索连接的正确方法.您正在检索连接并将其指定为类的实例(或更糟,静态)变量.基本上,您将永远保持连接打开,并为所有查询重用单个连接.如果查询由不同的线程执行,这可能最终导致灾难.此外,当它保持打开时间过长时,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;
}
Run Code Online (Sandbox Code Playgroud)

如果您担心连接性能并希望重用连接,那么您应该使用连接池.你可以养一个,但我强烈反对这一点,因为你似乎对这些东西很新.只需使用现有的连接池,如BoneCP,C3P0DBCP.请注意,您应该改变JDBC成语如在上面的例子.您仍然需要在尽可能短的范围内获取和关闭连接.连接池本身会担心实际重用,测试和/或关闭连接.

也可以看看:

  • 如果正确编写了JDBC代码,只需更改全局`getConnection()`方法,用`DataSource#getConnection()`替换`DriverManager#getConnection()`.有关具体示例,另请参见"另请参见"链接. (2认同)
  • 别客气.不要忘记在每次查询后关闭连接,以便它返回到池:) (2认同)