A Declaração Preparada é uma versão um pouco mais poderosa de uma Declaração e deve sempre ser pelo menos tão rápida e fácil de manusear quanto uma Declaração.
A declaração preparada pode ser parametrizada
A maioria dos bancos de dados relacionais manipula uma consulta JDBC / SQL em quatro etapas:
- Analisar a consulta SQL recebida
- Compile a consulta SQL
- Planejar / otimizar o caminho de aquisição de dados
- Execute a consulta / aquisição otimizada e retorne dados
Uma instrução sempre continuará com as quatro etapas acima para cada consulta SQL enviada ao banco de dados. Uma declaração preparada pré-executa as etapas (1) - (3) no processo de execução acima. Assim, ao criar uma instrução preparada, uma pré-otimização é realizada imediatamente. O efeito é diminuir a carga no mecanismo de banco de dados no tempo de execução.
Agora, minha pergunta é: "Existe alguma outra vantagem de usar a declaração preparada?"
Respostas:
Vantagens de um
PreparedStatement
:A pré-compilação e o armazenamento em cache do lado do banco de dados da instrução SQL levam à execução geral mais rápida e à capacidade de reutilizar a mesma instrução SQL em lotes .
Prevenção automática de ataques de injeção de SQL por escape interno de aspas e outros caracteres especiais. Observe que isso requer que você use qualquer um dos métodos para definir os valores
PreparedStatement
setXxx()
e, portanto , não inline os valores na string SQL concatenando a string.
Facilita a definição de objetos Java não-padrão em uma string SQL, por exemplo
Date
,Time
,Timestamp
,BigDecimal
,InputStream
(Blob
) eReader
(Clob
). Na maioria desses tipos, você não pode "apenas" fazer otoString()
que faria de uma maneira simplesStatement
. Você pode até refatorar tudo para usarPreparedStatement#setObject()
dentro de um loop, como demonstrado no método utilitário abaixo:Qual pode ser usado como abaixo:
fonte
Statement
, mas pode valer a pena um teste.Eles são pré-compilados (uma vez), mais rápidos para execução repetida de SQL dinâmico (onde os parâmetros mudam)
O cache da instrução do banco de dados aumenta o desempenho da execução do banco de dados
Os bancos de dados armazenam caches de planos de execução para instruções executadas anteriormente. Isso permite que o mecanismo de banco de dados reutilize os planos para instruções que foram executadas anteriormente. Como o PreparedStatement usa parâmetros, cada vez que é executado aparece como o mesmo SQL, o banco de dados pode reutilizar o plano de acesso anterior, reduzindo o processamento. As instruções "incorporam" os parâmetros na cadeia de caracteres SQL e, portanto, não aparecem como o mesmo SQL do banco de dados, impedindo o uso do cache.
Protocolo de comunicações binárias significa menos largura de banda e chamadas de comunicação mais rápidas para o servidor DB
Instruções preparadas são normalmente executadas através de um protocolo binário não-SQL. Isso significa que há menos dados nos pacotes, portanto, a comunicação com o servidor é mais rápida. Como regra geral, as operações de rede são uma ordem de magnitude mais lenta que as operações de disco, que são uma ordem de magnitude mais lenta que as operações de CPU na memória. Portanto, qualquer redução na quantidade de dados enviados pela rede terá um bom efeito no desempenho geral.
Eles protegem contra injeção de SQL, escapando do texto para todos os valores de parâmetro fornecidos.
Eles fornecem uma separação mais forte entre o código da consulta e os valores dos parâmetros (em comparação com as seqüências SQL concatenadas), aumentando a legibilidade e ajudando os mantenedores de código a entender rapidamente as entradas e saídas da consulta.
Em java, é possível chamar getMetadata () e getParameterMetadata () para refletir nos campos do conjunto de resultados e nos campos de parâmetro, respectivamente
Em java, aceita objetos java de forma inteligente como tipos de parâmetro via setObject, setBoolean, setByte, setDate, setDouble, setDouble, setFloat, setInt, setLong, setShort, setTime, setTimestamp - converte para o formato de tipo JDBC que é compreensível para DB (não apenas toString () formato).
Em java, aceita SQL ARRAYs, como tipo de parâmetro via método setArray
Em java, aceita CLOBs, BLOBs, OutputStreams e Readers como parâmetro "feeds" através dos métodos setClob / setNClob, setBlob, setBinaryStream, setCharacterStream / setAsciiStream / setNCharacterStream, respectivamente
Em java, permite que valores específicos do banco de dados sejam definidos para os métodos SQL DATALINK, SQL ROWID, SQL XML e NULL via setURL, setRowId, setSQLXML e setNull
Em java, herda todos os métodos de Statement. Ele herda o método addBatch e, além disso, permite que um conjunto de valores de parâmetros seja adicionado para corresponder ao conjunto de comandos SQL em lote via método addBatch.
Em java, um tipo especial de PreparedStatement (a subclasse CallableStatement) permite que procedimentos armazenados sejam executados - suportando alto desempenho, encapsulamento, programação procedural e SQL, administração / manutenção / ajuste de lógica / ajuste de lógica e uso de lógica e recursos proprietários de DB
fonte
Connection.createStatement
eConnection.prepareStatement
. Esse design obriga a trabalhar com interfaces, para que você não precise conhecer as classes de implementação específicas e evitar acoplamentos desnecessários com essas classes de implementação. Tudo explicado com exemplos nos documentos Java jdbc e Java. :)PreparedStatement
é uma defesa muito boa (mas não é infalível) na prevenção de ataques de injeção de SQL . Vincular valores de parâmetro é uma boa maneira de se proteger contra "pequenas mesas de Bobby", fazendo uma visita indesejada.fonte
ORDER BY
) e / ou constantes numéricas em certos lugares (penseLIMIT
,OFFSET
e outras soluções de paginação), assim que estes podem ser atacados por injeção de SQL, mesmo quando instruções preparadas e parametrização é usado sempre que possível.Alguns dos benefícios do PreparedStatement over Statement são:
Leia mais sobre o problema de injeção de SQL em http://www.journaldev.com/2489/jdbc-statement-vs-preparedstatement-sql-injection-example
fonte
nada a acrescentar,
1 - se você deseja executar uma consulta em um loop (mais de uma vez), a instrução preparada pode ser mais rápida, devido à otimização que você mencionou.
A consulta com 2 parâmetros é uma boa maneira de evitar a injeção de SQL. As consultas parametrizadas estão disponíveis apenas no PreparedStatement.
fonte
A declaração é estática e a declaração preparada é dinâmica.
A instrução é adequada para DDL e declaração preparada para DML.
A declaração é mais lenta, enquanto a declaração preparada é mais rápida.
mais diferenças (arquivadas)
fonte
Não é possível executar CLOBs em uma instrução.
E: (OraclePreparedStatement) ps
fonte
Citado por mattjames
fonte
a injeção de sql é ignorada pela instrução preparada, para que a segurança seja aumentada na instrução preparada
fonte
fonte
A instrução será usada para executar instruções SQL estáticas e não pode aceitar parâmetros de entrada.
PreparedStatement será usado para executar instruções SQL muitas vezes dinamicamente. Aceitará parâmetros de entrada.
fonte
Outra característica da Consulta Preparada ou Parametrizada: Referência retirada deste artigo.
Essa instrução é um dos recursos do sistema de banco de dados no qual a mesma instrução SQL é executada repetidamente com alta eficiência. As instruções preparadas são um tipo de modelo e usadas por aplicativos com parâmetros diferentes.
O modelo de instrução é preparado e enviado ao sistema de banco de dados e o sistema de banco de dados executa a análise, compilação e otimização nesse modelo e armazena-o sem executá-lo.
Alguns parâmetros como, em que a cláusula não é passada durante a aplicação posterior da criação do modelo, enviam esses parâmetros para o sistema de banco de dados e o sistema de banco de dados usa o modelo da Instrução SQL e é executado conforme a solicitação.
As instruções preparadas são muito úteis no SQL Injection, porque o aplicativo pode preparar parâmetros usando diferentes técnicas e protocolos.
Quando o número de dados está aumentando e os índices estão mudando com frequência naquele momento, as Instruções Preparadas podem falhar, pois nessa situação requer um novo plano de consulta.
fonte
Statement
interface executa instruções SQL estáticas sem parâmetrosPreparedStatement
interface (estendendo a instrução) executa uma instrução SQL pré-compilada com / sem parâmetrosEficiente para execuções repetidas
Como pré-compilado, é mais rápido
fonte
Não fique confuso: basta lembrar
fonte
Eu segui todas as respostas desta pergunta para alterar um código legado em funcionamento usando -
Statement
(mas com injeções SQL) para uma solução usandoPreparedStatement
um código muito mais lento por causa do fraco entendimento da semântica em torno doStatement.addBatch(String sql)
&PreparedStatement.addBatch()
.Então, estou listando meu cenário aqui para que outros não cometam o mesmo erro.
Meu cenário foi
Portanto, no código acima, eu tinha milhares de consultas diferentes, todas adicionadas à mesma instrução e esse código funcionava mais rápido porque as instruções que não estavam sendo armazenadas em cache eram boas e esse código era executado raramente no aplicativo.
Agora, para corrigir as injeções de SQL, alterei esse código para,
Entenda, comecei a criar milhares de
PreparedStatement
objetos e, eventualmente, não consegui utilizar lotes porque meu cenário exigia isso - existem milhares de consultas UPDATE ou INSERT e todas essas consultas são diferentes.A correção da injeção de SQL era obrigatória sem nenhum custo de degradação do desempenho e não acho que isso seja possível
PreparedStatement
nesse cenário.Além disso, ao usar o recurso de lote embutido, você precisa se preocupar em fechar apenas uma instrução, mas com essa abordagem da lista, é necessário fechar a instrução antes de reutilizá-la, reutilizando uma declaração preparada
fonte