Можно ли использовать один и тот же BasicDataSource, Connection, Statement и ResultSet Object в нескольких методах класса? - PullRequest
0 голосов
/ 06 марта 2019

У меня есть код ниже, который использует статические объекты BasicDataSource, Sql Connection, Statement и ResultSet. Приведенный ниже код работает нормально, но я просто хочу узнать о безопасности использования подобных методов кодирования. или как я могу оптимизировать приведенный ниже код, чтобы он стал более стабильным и надежным.

public class Testing {
     static BasicDataSource bds = DBConnection.getInstance().getBds();
     static Connection con = null;
     static PreparedStatement stmt = null;
     static ResultSet rs = null;

    private void show() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("SELECT * FROM users");
            rs = stmt.executeQuery();
            if(rs.next()) {
                System.out.println(rs.getString("firstname") + " " + rs.getString("lastname"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    private void display() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("SELECT * FROM agent_cities");
            rs = stmt.executeQuery();
            while(rs.next()) {
                System.out.println(rs.getString("city_name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    private void add() {
        try {
            con = bds.getConnection();
            stmt = con.prepareStatement("UPDATE users SET firstname = 'shsh' WHERE id = 2");
            stmt.executeUpdate();
            System.out.println("updated successfully");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Testing t = new Testing();
        t.show();
        t.display();
        t.add();
    }
}

Спасибо заранее. Поделитесь своими случаями, в которых вы можете нарушить приведенный выше код, и задать вопрос о его безопасности.

Обновление: Обновление только для того, чтобы никто не использовал статические поля, как я использовал в вышеприведенной программе, потому что вышеприведенная программа содержит ошибку при развертывании на сервере dev.

После использования приведенного выше кода на больших системах я обнаружил ошибку. месяц назад у меня не было проблем с приведенным выше кодом, и он работал нормально, но сегодня я нашел ошибку.

Ошибка:

После попадания в мои API 6-7 раз он перестал давать ответ при 8-м попадании. Я действительно не знаю почему и понятия не имею о дырках в программе. Но теперь, когда я принял ответ, я изменил свой исходный код и начал использовать в своем коде ресурсы try-with и удалил статические поля.

Но мне все еще интересно узнать об ошибке, обнаруженной в приведенном выше коде. это не дает ответа и зависает после 7-8 попаданий API. Пожалуйста, поделитесь своими мыслями по этому поводу. Я использую сервер Apache Tomcat 8.5.32. Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 06 марта 2019

Лучше использовать try-with-resources .Это автоматически закрывает Connection, Statement и ResultSet даже при возникновении исключения или при внутреннем возврате.

    String sql = "UPDATE users SET firstname = ? WHERE id = ?";
    try (Connection con = bds.getConnection();
            PreparedStatement stmt = con.prepareStatement()) {
        stmt.setString(1, "shsh");
        stmt.setLong(2, 2);
        stmt.executeUpdate();
        System.out.println("updated successfully");
    }

    String sql = "SELECT city_name FROM agent_cities";
    try (Connection con = bds.getConnection();
            PreparedStatement stmt = con.prepareStatement()) {
        try (ResultSet rs = stmt.executeQuery()) {
            while(rs.next()) {
                System.out.println(rs.getString("city_name"));
            }
        }
    }

Это лучше для сборки мусора.Предотвращает unnice RS2, RS3.Разрешает многопользовательский параллелизм, как в серверном приложении.Звонки, которые запрашивают сами.И static еще больше в стиле глобальных переменных.

1 голос
/ 06 марта 2019

Это более или менее нормально, если мы говорим о такой маленькой программе.Но нет необходимости хранить con, stmt и rs как статические переменные, они могут быть объявлены внутри метода.Кроме того, вам нужно переписать блоки try try и правильно закрыть ресурсы:

Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
  // your code
} catch (SQLException e) {
  e.printStackTrace();
} finally {
  try { if (rs != null) rs.close(); } catch (Exception e) {e.printStackTrace();}
  try { if (stmt != null) stmt.close(); } catch (Exception e) {e.printStackTrace();}
  try { if (conn != null) conn.close(); } catch (Exception e) {e.printStackTrace();}
}

В качестве следующего шага вы можете проверить конструкцию try-with-resources , чтобы очистить этот код.

0 голосов
/ 21 мая 2019

Вы должны использовать try-with-resources, чтобы избежать любых утечек соединения.

В следующем примере выполняется чтение первой строки из файла.Он использует экземпляр BufferedReader для чтения данных из файла.BufferedReader - это ресурс, который должен быть закрыт после завершения работы программы:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}
...