Когда мое приложение теряет соединение, как мне его восстановить? - PullRequest
4 голосов
/ 01 декабря 2011

У меня есть приложение, которое я подключаю к базе данных 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;
}

В методе 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 ]

15 голосов
/ 01 декабря 2011

Это неправильный способ получения соединения.Вы извлекаете соединение и назначаете его в качестве экземпляра (или, что еще хуже, статической) переменной класса.По сути, вы сохраняете соединение открытым навсегда и повторно используете одно соединение для всех запросов.Это может привести к катастрофе, если запросы выполняются разными потоками.Кроме того, когда он остается открытым слишком долго, БД восстановит его, поскольку предполагает, что он мертв / утечка.

Вы должны получить и закрыть соединение в кратчайшем возможная область применения .Т.е. в том же блоке 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, как показано в примере выше.Вам все еще нужно приобрести и закрыть соединение в кратчайшие сроки.Пул соединений сам по себе будет беспокоиться о фактическом повторном использовании, тестировании и / или закрытии соединения.

См. Также:

0 голосов
/ 01 декабря 2011
0 голосов
/ 01 декабря 2011

Откуда в вашем коде возникают ошибки при потере соединения?Скорее всего, это было бы лучшим началомне удалось до тех пор, пока вы не попытаетесь что-то сделать.

В прошлом я делал недействительным соединение в точке сбоя и периодически повторял.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...