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

时间:2011-12-01 16:52:03

标签: java jdbc database-connection

我有一个应用程序,我正在连接到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;
}

我可以在这两种方法中改变什么来容纳失去联系?

3 个答案:

答案 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;
}

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

另见:

答案 1 :(得分:0)

代码中的哪个位置是丢失连接的错误?这可能是最好的起点。

脱离我的头脑(我可能错了),JDBC连接只会在实际致命错误时关闭,所以在你尝试做某事之前你不会知道它们已经失败了。

我过去所做的是在失败时使连接无效并定期重试。

答案 2 :(得分:0)