Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Statement fica em aberto?

No código:

public class TestaInsercao {

    public static void main(String[] args) throws SQLException, IllegalAccessException {

        Connection connection = Database.getConnection();
        connection.setAutoCommit(false);

        PreparedStatement statement;
        try {
            String sql = "INSERT INTO Produto(nome, descricao) VALUES (?, ?)";
            statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

            adiciona("TV LCD", "32 polegadas", statement);
            adiciona("Blueray", "Full HDMI", statement);
            connection.commit();
            statement.close();
        } catch (Exception e) {
            e.printStackTrace();
            connection.rollback();
        }

        connection.close();

    }

E função

private static void adiciona(String nome, String descricao, PreparedStatement statement) throws SQLException, IllegalAccessException {

        if (nome.equals("Blueray")) {
            throw new IllegalAccessException("Problema ocorrido");
        }

        statement.setString(1, nome);
        statement.setString(2, descricao);

        boolean resultado = statement.execute();
        System.out.println(resultado);

        ResultSet resultSet = statement.getGeneratedKeys();

        while (resultSet.next()) {
            String string = resultSet.getString("id");
            System.out.println(string);
        }
    }

}

Caso houvesse um erro no 2o adiciona (que adiciona o Blueray), o statement não ira ficar em aberto (já que o programa pularia para o catch e não chegaria no close) ?

4 respostas

O mais correto seria o statement.close(); dentro do catch mesmo (ou de um finally)

Foi o que pensei, mas o close não compila nem dentro do catch nem dentro do Finally, já que ele só é aberto no try.

solução!

A partir do Java 7, foi adicionado o "try-with-resources", onde você pode inicializar a conexão e efetua a consulta ainda no comando try, fazendo isso, o comando fica responsável por chamar o método ".close()" das variáveis declaradas que implementam a interface java.lang.AutoCloseable" (todos os rescursos declarados aqui devem implementar a interface). Para saber como utilizar e mais detalhes, basta ler a documentação da Oracle a seguir: Documentação Oracle - Try Resource Close

Uma solução para versões anteriores, seguindo o código passado seria verificar o "statement" e a "connection" no escopo do "finally" que vem após ao catch, gerando um código semelhante a esse:

public static void main(String[] args) throws SQLException, IllegalAccessException {

    Connection connection = null;
    PreparedStatement statement = null;

    try {
        connection = Database.getConnection();
        connection.setAutoCommit(false);

        String sql = "INSERT INTO Produto(nome, descricao) VALUES (?, ?)";
        statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

        adiciona("TV LCD", "32 polegadas", statement);
        adiciona("Blueray", "Full HDMI", statement);

        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
        connection.rollback();
    } finally {

        if (statement != null && !statement.isClosed()) {
            statement.close();
        }

        if (connection != null && !connection.isClosed()) {
            connection.close();
        }
    }
}

Outro ponto importante a ser ressaltado é que o "ResultSet" gerado pelo "PrepareStatement" também precisa ser fechado após fazer uso do mesmo, sendo assim seria necessário declará-lo antes do "try", em seguida seu resultado ainda dentro do escopo do "try" e efetuar o close no escopo do "finally" (em soluções com java em versões anteriores à 7).

Muito Obrigado Wensttay! Respondeu exatamente a dúvida que eu tinha.

Nos vídeos seguintes, o instrutor fala sobre o try with resources, que o statement é AutoCloseable, como você explicou.

Mas fiquei pensando, "E como era feito antes do Java 7". Não tinha pensado em usar um if..

Muito Obrigado!!!