Mam ogólną metodę Java z następującą sygnaturą metody:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Otwiera połączenie, buduje za PreparedStatement
pomocą instrukcji sql i parametrów w queryParams
tablicy o zmiennej długości, uruchamia je, buforuje ResultSet
(w a CachedRowSetImpl
), zamyka połączenie i zwraca zbuforowany zestaw wyników.
Mam obsługę wyjątków w metodzie, która rejestruje błędy. Loguję instrukcję sql jako część dziennika, ponieważ jest ona bardzo pomocna przy debugowaniu. Mój problem polega na tym, że rejestrowanie zmiennej String sql
rejestruje instrukcję szablonu z? Zamiast rzeczywistych wartości. Chcę zarejestrować rzeczywistą instrukcję, która została wykonana (lub próbowała wykonać).
Więc ... Czy istnieje sposób, aby uzyskać rzeczywistą instrukcję SQL, która zostanie uruchomiona przez PreparedStatement
? ( Bez budowania go samodzielnie. Jeśli nie mogę znaleźć sposobu na uzyskanie dostępu do PreparedStatement's
SQL, prawdopodobnie utworzę go samodzielnie w moich catch
es).
źródło
Odpowiedzi:
Korzystając z przygotowanych wyciągów nie ma „zapytania SQL”:
Ale nie ma rekonstrukcji rzeczywistego zapytania SQL - ani po stronie Java, ani po stronie bazy danych.
Nie ma więc możliwości uzyskania SQL przygotowanej instrukcji - bo takiego SQL nie ma.
W celu debugowania rozwiązania są następujące:
źródło
Nigdzie nie jest to zdefiniowane w umowie JDBC API, ale jeśli masz szczęście, dany sterownik JDBC może zwrócić pełny kod SQL, po prostu wywołując
PreparedStatement#toString()
. To znaczyObsługują go przynajmniej sterowniki JDBC MySQL 5.xi PostgreSQL 8.x. Jednak większość innych sterowników JDBC go nie obsługuje. Jeśli masz taki, najlepszym rozwiązaniem jest użycie Log4jdbc lub P6Spy .
Alternatywnie można również napisać funkcję ogólną, która pobiera
Connection
ciąg znaków SQL i wartości instrukcji i zwracaPreparedStatement
po zarejestrowaniu ciągu SQL i wartości. Przykład rozpoczęcia:i używaj go jako
Inną alternatywą jest zaimplementowanie niestandardowego,
PreparedStatement
który zawija (ozdabia) rzeczywistośćPreparedStatement
w konstrukcji i przesłania wszystkie metody, tak że wywołuje metody wartości rzeczywistejPreparedStatement
i zbiera wartości we wszystkichsetXXX()
metodach i leniwie konstruuje „rzeczywisty” ciąg SQL za każdym razem, gdy jeden z teexecuteXXX()
metody nazywa się (dość pracy, ale większość IDE zapewnia autogenerators metod dekorator, Eclipse robi). Wreszcie po prostu użyj go. To także w zasadzie to, co P6Spy i konsorci już robią pod maskami.źródło
logger.debug(sql + " " + Arrays.asList(values))
- szukam sposobu na zalogowanie instrukcji sql z parametrami już w niej zintegrowanymi. Bez zapętlania się i zastępowania znaków zapytania.PreparedStatement
każdym razem. Czy nie będzie to tak wydajne, ponieważ chodzi oPreparedStatement
to, aby je raz stworzyć i wykorzystać wszędzie?Używam Java 8, sterownika JDBC ze złączem MySQL v. 5.1.31.
Mogę uzyskać prawdziwy ciąg SQL za pomocą tej metody:
Więc zwraca coś takiego:
źródło
Apache Derby
?Jeśli wykonanie zapytania i spodziewa się
ResultSet
(jesteś w takiej sytuacji, co najmniej), to możesz po prostu zadzwonićResultSet
„sgetStatement()
tak:Zmienna
executedQuery
będzie zawierać instrukcję, która została użyta do utworzenia plikuResultSet
.Teraz zdaję sobie sprawę, że to pytanie jest dość stare, ale mam nadzieję, że to komuś pomoże ...
źródło
Wyodrębniłem mój sql z PreparedStatement przy użyciu przygotowanejStatement.toString () W moim przypadku toString () zwraca String w następujący sposób:
Teraz stworzyłem metodę (Java 8), która używa wyrażenia regularnego do wyodrębnienia zarówno zapytania, jak i wartości i umieszczenia ich w mapie:
Ta metoda zwraca mapę, w której mamy pary klucz-wartość:
Teraz - jeśli chcesz, aby wartości były listą, możesz po prostu użyć:
Jeśli twoja metoda readyStatement.toString () jest inna niż w moim przypadku, jest to tylko kwestia „dostosowania” wyrażenia regularnego.
źródło
Używanie PostgreSQL 9.6.x z oficjalnym sterownikiem Java
42.2.4
:Pokaże SQL z
?
już zastąpionym, czego szukałem. Właśnie dodałem tę odpowiedź, aby objąć przypadek postgres.Nigdy bym nie pomyślał, że to może być takie proste.
źródło
Zaimplementowałem następujący kod do drukowania SQL z PrepareStatement
źródło
Fragment kodu do konwersji SQL PreparedStaments z listą argumentów. Mi to pasuje
źródło
Bardzo późno :), ale oryginalny SQL można pobrać z OraclePreparedStatementWrapper przez
źródło
oracle.jdbc.driver.OraclePreparedStatementWrapper
nie jest publicznie w oracle.jdbc.driver. Nie można uzyskać dostępu z zewnątrz pakietu. Jak korzystasz z tej klasy?Jeśli używasz MySQL, możesz rejestrować zapytania za pomocą dziennika zapytań MySQL . Nie wiem, czy inni dostawcy zapewniają tę funkcję, ale są szanse, że tak.
źródło
Po prostu działaj:
Jest dobrze, jak również dla przygotowanego oświadczenia.
źródło
.toString()
z kilkoma dodatkowymi wierszami, aby oszukać niedoświadczonych użytkowników, i odpowiedź została udzielona już wieki temu.Używam Oralce 11g i nie udało mi się uzyskać końcowego kodu SQL z PreparedStatement. Po przeczytaniu odpowiedzi @ Pascal MARTIN rozumiem dlaczego.
Po prostu porzuciłem pomysł korzystania z PreparedStatement i użyłem prostego programu do formatowania tekstu, który pasował do moich potrzeb. Oto mój przykład:
Dowiesz się, że sqlInParam można zbudować dynamicznie w pętli (for, while). Po prostu sprawiłem, że dotarcie do punktu użycia klasy MessageFormat jako elementu formatującego szablon ciągu dla zapytania SQL jest bardzo proste.
źródło
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Aby to zrobić, potrzebujesz połączenia JDBC i / lub sterownika obsługującego logowanie sql na niskim poziomie.
Spójrz na log4jdbc
źródło