Eu tenho um método Java geral com a seguinte assinatura de método:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Ele abre uma conexão, cria um PreparedStatement
usando a instrução sql e os parâmetros na queryParams
matriz de comprimento variável, a executa, armazena ResultSet
em cache o (em a CachedRowSetImpl
), fecha a conexão e retorna o conjunto de resultados em cache.
Eu tenho manipulação de exceção no método que registra erros. Registro a instrução sql como parte do log, pois é muito útil para depuração. Meu problema é que o registro da variável String sql
registra a instrução do modelo com? Em vez de valores reais. Quero registrar a instrução real que foi executada (ou tentou executar).
Então ... Existe alguma maneira de obter a instrução SQL real que será executada por um PreparedStatement
? ( Sem construí-lo eu mesmo. Se não conseguir encontrar uma maneira de acessar o PreparedStatement's
SQL, provavelmente acabarei construindo ele mesmo em meus catch
es.)
fonte
Respostas:
Usando instruções preparadas, não há "consulta SQL":
Mas não há reconstrução de uma consulta SQL real real - nem no lado Java nem no lado do banco de dados.
Portanto, não há como obter o SQL da instrução preparada - pois não existe esse SQL.
Para fins de depuração, as soluções são:
fonte
Não está definido em nenhum lugar no contrato da API JDBC, mas se você tiver sorte, o driver JDBC em questão pode retornar o SQL completo apenas ligando
PreparedStatement#toString()
. Ou seja,Pelo menos os drivers MySQL 5.xe PostgreSQL 8.x JDBC suportam. No entanto, a maioria dos outros drivers JDBC não é compatível. Se você tiver esse, sua melhor aposta é usar o Log4jdbc ou o P6Spy .
Como alternativa, você também pode escrever uma função genérica que use a
Connection
, uma string SQL e os valores da instrução e retorne aPreparedStatement
depois de registrar a string SQL e os valores. Exemplo inicial:e use-o como
Outra alternativa é implementar um costume
PreparedStatement
que envolve (decora) o realPreparedStatement
na construção e substitui todos os métodos para que ele chame os métodos do realPreparedStatement
e colete os valores em todos ossetXXX()
métodos e construa preguiçosamente a string SQL "real" sempre que um dos osexecuteXXX()
métodos são chamados (bastante trabalho, mas a maioria dos IDEs fornece geradores automáticos para métodos de decorador, o Eclipse fornece). Finalmente, basta usá-lo. Isso também é basicamente o que o P6Spy e os consortes já fazem sob o capô.fonte
logger.debug(sql + " " + Arrays.asList(values))
- estou procurando uma maneira de registrar a instrução sql com os parâmetros já integrados a ela. Sem me dar laços e substituir os pontos de interrogação.PreparedStatement
sempre. Não será esse o caminho não tão eficiente, porque o ponto principalPreparedStatement
é criá-los uma vez e reutilizá-los em qualquer lugar?Estou usando o Java 8, driver JDBC com conector MySQL v. 5.1.31.
Eu posso obter uma string SQL real usando este método:
Então, ele retorna smth assim:
fonte
Apache Derby
?Se você estiver executando a consulta e esperando uma
ResultSet
(você está nesse cenário, pelo menos), basta chamarResultSet
da seguintegetStatement()
maneira:A variável
executedQuery
irá conter a afirmação de que foi usado para criar oResultSet
.Agora, percebo que essa pergunta é bastante antiga, mas espero que isso ajude alguém.
fonte
Eu extraí meu sql do PreparedStatement usando o preparadoStatement.toString () No meu caso, toString () retorna String assim:
Agora eu criei um método (Java 8), que está usando o regex para extrair a consulta e os valores e colocá-los no mapa:
Este método retorna o mapa onde temos pares de valores-chave:
Agora - se você deseja valores como lista, pode simplesmente usar:
Se o seu preparadoStatement.toString () for diferente do meu caso, é apenas uma questão de "ajustar" a expressão regular.
fonte
Usando o PostgreSQL 9.6.x com o driver Java oficial
42.2.4
:Mostrará o SQL com o
?
já substituído, que é o que eu estava procurando. Acabei de adicionar esta resposta para cobrir o caso do postgres.Eu nunca teria pensado que poderia ser tão simples.
fonte
Eu implementei o seguinte código para imprimir SQL a partir de PrepareStatement
fonte
Snippet de código para converter SQL PreparedStaments com a lista de argumentos. Funciona para mim
fonte
Muito tarde :), mas você pode obter o SQL original de um OraclePreparedStatementWrapper por
fonte
oracle.jdbc.driver.OraclePreparedStatementWrapper
não é público no oracle.jdbc.driver. Não pode ser acessado a partir do pacote externo. Como você está usando essa classe?Se você estiver usando o MySQL, poderá registrar as consultas usando o log de consultas do MySQL . Não sei se outros fornecedores fornecem esse recurso, mas é provável que sim.
fonte
Simplesmente função:
Também está bom para a declaração preparada.
fonte
.toString()
com algumas linhas extras para enganar usuários inexperientes, e já foi respondido há séculos.Estou usando o Oralce 11g e não consegui obter o SQL final do PreparedStatement. Depois de ler a resposta do @Pascal MARTIN, entendo o porquê.
Acabei de abandonar a ideia de usar PreparedStatement e usei um formatador de texto simples que atendesse às minhas necessidades. Aqui está o meu exemplo:
Você descobre que o sqlInParam pode ser criado dinamicamente em um loop (for, while). Simplesmente simplifiquei o ponto de usar a classe MessageFormat para servir como formador de modelo de string para a consulta SQL.
fonte
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Para fazer isso, você precisa de uma conexão JDBC e / ou driver que suporte o log do sql em um nível baixo.
Dê uma olhada no log4jdbc
fonte