[SQL] 어떻게 된 PreparedStatement의 SQL을받을 수 있나요?
SQL어떻게 된 PreparedStatement의 SQL을받을 수 있나요?
나는 다음과 같은 방법 서명 일반적인 자바 방법이있다 :
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
그것은, 연결을 여는 queryParams에서 SQL 문 및 매개 변수 가변 길이 배열을 사용하여 PreparedStatement의를 구축, 그것을 실행 (A CachedRowSetImpl에서) 결과 집합을 캐시, 연결, 반환 캐시 된 결과 집합을 닫습니다.
나는 로그 오류 그 방법에있어서 예외 처리가 있습니다. 이 디버깅에 매우 도움이 이후는 로그의 일부로서 SQL 문을 로그. 내 문제는 '? String 변수의 SQL을 기록하는 것은으로 템플릿 구문을 기록한다는 것입니다 대신 실제 값의이야. 나는 실행 (또는 실행하려고) 된 실제 문을 로그합니다.
그래서 ... 해, PreparedStatement에 의해 실행됩니다 실제 SQL 문을 얻을 수있는 방법이 있습니까? (그것을 자신을 구축하지 않고. 나는 아마 내 어획량에 나 자신을 구축하게 될 겁니다, PreparedStatement의의 SQL에 액세스 할 수있는 방법을 찾을 수없는 경우.)
해결법
-
==============================
1.준비된 문을 사용하여, "SQL 쿼리는"없다 :
준비된 문을 사용하여, "SQL 쿼리는"없다 :
그러나 실제 실제 SQL 쿼리에는 재 건설이 없습니다 - 어느 자바 측 않으며, 데이터베이스 측에서.
그래서, 준비된 명령문의 SQL을 얻을 수있는 방법이 없습니다 - 이러한 SQL 없기 때문에.
디버깅 목적을 위해, 솔루션 중 하나를 할 수 있습니다 :
-
==============================
2.이 곳은 JDBC API 계약에 정의되어 있지,하지만 당신이 운이 좋다면, 문제의 JDBC 드라이버는 PreparedStatement의 # toString ()를 호출하여 전체 SQL을 반환 할 수 있습니다. 즉
이 곳은 JDBC API 계약에 정의되어 있지,하지만 당신이 운이 좋다면, 문제의 JDBC 드라이버는 PreparedStatement의 # toString ()를 호출하여 전체 SQL을 반환 할 수 있습니다. 즉
System.out.println(preparedStatement);
적어도 MySQL의 5.x 및 PostgreSQL을 8.x의 JDBC 드라이버에서이를 지원합니다. 그러나, 대부분의 다른 JDBC 드라이버를 지원하지 않습니다. 당신은 그런 일이 있다면, 가장 좋은 건 Log4jdbc 또는 P6Spy로를 사용하고 있습니다.
또한, 당신은 또한 연결, SQL 문자열과 문 값을 사용하여 SQL 문자열과 값을 기록 후 PreparedStatement로를 반환하는 일반적인 함수를 작성할 수 있습니다. 킥오프 예 :
public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException { PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < values.length; i++) { preparedStatement.setObject(i + 1, values[i]); } logger.debug(sql + " " + Arrays.asList(values)); return preparedStatement; }
및로 사용
try { connection = database.getConnection(); preparedStatement = prepareStatement(connection, SQL, values); resultSet = preparedStatement.executeQuery(); // ...
또 다른 대안은 랩 (장식) 사용자 정의 된 PreparedStatement 건설에 실제의 PreparedStatement를 구현하는 것입니다 그리고 그것은 실제의 PreparedStatement의 메소드를 호출하고 모든의 setXXX () 메소드의 값을 수집하는 그래서 모든 방법을 무시하고 유유히 "실제를 구축 "SQL 상기 executeXXX () 메소드 중 하나가 호출 될 때마다 문자열 (아주 작동하지만 IDE의은 장식 방법에 대한 autogenerators을 제공 대부분의 이클립스는 않습니다). 마지막으로 단지 대신 사용하십시오. 즉 P6Spy로와 배우자들 이미 후드에서 할 기본적으로 어떤이기도합니다.
-
==============================
3.나는, MySQL의 커넥터 v와 JDBC 드라이버. 5.1.31 자바 8을 사용하고 있습니다.
나는, MySQL의 커넥터 v와 JDBC 드라이버. 5.1.31 자바 8을 사용하고 있습니다.
나는이 방법을 사용하여 실제 SQL 문자열을 얻을 수 있습니다 :
// 1. make connection somehow, it's conn variable // 2. make prepered statement template PreparedStatement stmt = conn.prepareStatement( "INSERT INTO oc_manufacturer" + " SET" + " manufacturer_id = ?," + " name = ?," + " sort_order=0;" ); // 3. fill template stmt.setInt(1, 23); stmt.setString(2, 'Google'); // 4. print sql string System.out.println(((JDBC4PreparedStatement)stmt).asSql());
그래서 다음과 같이 떨어지게을 반환합니다 :
INSERT INTO oc_manufacturer SET manufacturer_id = 23, name = 'Google', sort_order=0;
-
==============================
4.당신은 쿼리를 실행하고 결과 집합 (당신이 적어도,이 시나리오에) 당신은 단순히과 같이의 ResultSet의 getStatement ()를 호출 할 수 있습니다 기대하는 경우 :
당신은 쿼리를 실행하고 결과 집합 (당신이 적어도,이 시나리오에) 당신은 단순히과 같이의 ResultSet의 getStatement ()를 호출 할 수 있습니다 기대하는 경우 :
ResultSet rs = pstmt.executeQuery(); String executedQuery = rs.getStatement().toString();
변수의 executedQuery는 결과 집합을 만드는 데 사용 된 문이 포함됩니다.
지금, 나는이 질문은 꽤 오래 실현,하지만 난이 사람을 도움이되기를 바랍니다 ..
-
==============================
5.나는 () 같은 문자열을 반환 내 경우의 된 toString preparedStatement.toString ()를 사용하여 PreparedStatement로에서 나의 SQL을 추출했습니다
나는 () 같은 문자열을 반환 내 경우의 된 toString preparedStatement.toString ()를 사용하여 PreparedStatement로에서 나의 SQL을 추출했습니다
org.hsqldb.jdbc.JDBCPreparedStatement@7098b907[sql=[INSERT INTO TABLE_NAME(COLUMN_NAME, COLUMN_NAME, COLUMN_NAME) VALUES(?, ?, ?)], parameters=[[value], [value], [value]]]
지금은 쿼리 값을 모두 추출하고지도로 넣어 정규식을 사용하는 방법 (자바 8)를 만들었습니다 :
private Map<String, String> extractSql(PreparedStatement preparedStatement) { Map<String, String> extractedParameters = new HashMap<>(); Pattern pattern = Pattern.compile(".*\\[sql=\\[(.*)],\\sparameters=\\[(.*)]].*"); Matcher matcher = pattern.matcher(preparedStatement.toString()); while (matcher.find()) { extractedParameters.put("query", matcher.group(1)); extractedParameters.put("values", Stream.of(matcher.group(2).split(",")) .map(line -> line.replaceAll("(\\[|])", "")) .collect(Collectors.joining(", "))); } return extractedParameters; }
우리가 키 - 값 쌍을 가질 경우이 방법을 반환지도 :
"query" -> "INSERT INTO TABLE_NAME(COLUMN_NAME, COLUMN_NAME, COLUMN_NAME) VALUES(?, ?, ?)" "values" -> "value, value, value"
- 지금 당신은 당신이 단지 사용할 수있는 목록으로 값을 원하는 경우 :
List<String> values = Stream.of(yourExtractedParametersMap.get("values").split(",")) .collect(Collectors.toList());
당신의 preparedStatement.toString이 () 내 경우에는 다른 경우 그냥 "조정"정규식의 문제이다.
-
==============================
6.나는의 prepareStatement에서 SQL을 인쇄하기 위해 다음과 같은 코드를 구현
나는의 prepareStatement에서 SQL을 인쇄하기 위해 다음과 같은 코드를 구현
public void printSqlStatement(PreparedStatement preparedStatement, String sql) throws SQLException{ String[] sqlArrya= new String[preparedStatement.getParameterMetaData().getParameterCount()]; try { Pattern pattern = Pattern.compile("\\?"); Matcher matcher = pattern.matcher(sql); StringBuffer sb = new StringBuffer(); int indx = 1; // Parameter begin with index 1 while (matcher.find()) { matcher.appendReplacement(sb,String.valueOf(sqlArrya[indx])); } matcher.appendTail(sb); System.out.println("Executing Query [" + sb.toString() + "] with Database[" + "] ..."); } catch (Exception ex) { System.out.println("Executing Query [" + sql + "] with Database[" + "] ..."); } }
-
==============================
7.아주 늦게 :)하지만 당신은 OraclePreparedStatementWrapper에서 원래 SQL에 의해 얻을 수 있습니다
아주 늦게 :)하지만 당신은 OraclePreparedStatementWrapper에서 원래 SQL에 의해 얻을 수 있습니다
((OraclePreparedStatementWrapper) preparedStatement).getOriginalSql();
-
==============================
8.공식 자바 드라이버 42.2.4와 PostgreSQL의 9.6.x를 사용 :
공식 자바 드라이버 42.2.4와 PostgreSQL의 9.6.x를 사용 :
...myPreparedStatement.execute... myPreparedStatement.toString()
와 SQL을 보여 것인가? 이미 내가 찾던 인 대체했다. 그냥 포스트 그레스 케이스를 커버하는이 대답을했다.
나는 간단 있도록 할 수 있다고 생각하지 않았을 것이다.
-
==============================
9.당신이 MySQL을 사용하는 경우 당신은 MySQL의 쿼리 로그를 사용하여 쿼리를 로그인 할 수 있습니다. 다른 공급 업체가이 기능을 제공하는 경우는 모르겠지만, 기회는 그들이 할 수 있습니다.
당신이 MySQL을 사용하는 경우 당신은 MySQL의 쿼리 로그를 사용하여 쿼리를 로그인 할 수 있습니다. 다른 공급 업체가이 기능을 제공하는 경우는 모르겠지만, 기회는 그들이 할 수 있습니다.
-
==============================
10.코드 조각은 인수 목록에서 SQL PreparedStaments을 변환합니다. 그것은 나를 위해 작동
코드 조각은 인수 목록에서 SQL PreparedStaments을 변환합니다. 그것은 나를 위해 작동
/** * * formatQuery Utility function which will convert SQL * * @param sql * @param arguments * @return */ public static String formatQuery(final String sql, Object... arguments) { if (arguments != null && arguments.length <= 0) { return sql; } String query = sql; int count = 0; while (query.matches("(.*)\\?(.*)")) { query = query.replaceFirst("\\?", "{" + count + "}"); count++; } String formatedString = java.text.MessageFormat.format(query, arguments); return formatedString; }
-
==============================
11.간단히 기능 :
간단히 기능 :
public static String getSQL (Statement stmt){ String tempSQL = stmt.toString(); //please cut everything before sql from statement //javadb...: int i1 = tempSQL.indexOf(":")+2; tempSQL = tempSQL.substring(i1); return tempSQL; }
이 PreparedStatement의 벌금 aswell이다.
-
==============================
12.나는 오라클 11g를 사용하고 있는데 PreparedStatement의에서 최종 SQL을 얻을 관리 할 수 있습니다. @Pascal MARTIN 답변을 읽은 후 그 이유를 이해합니다.
나는 오라클 11g를 사용하고 있는데 PreparedStatement의에서 최종 SQL을 얻을 관리 할 수 있습니다. @Pascal MARTIN 답변을 읽은 후 그 이유를 이해합니다.
난 그냥 된 PreparedStatement를 사용하는 아이디어를 포기하고 내 요구를 장착 간단한 텍스트 포맷을 사용했다. 여기 내 예입니다 :
//I jump to the point after connexion has been made ... java.sql.Statement stmt = cnx.createStatement(); String sqlTemplate = "SELECT * FROM Users WHERE Id IN ({0})"; String sqlInParam = "21,34,3434,32"; //some random ids String sqlFinalSql = java.text.MesssageFormat(sqlTemplate,sqlInParam); System.out.println("SQL : " + sqlFinalSql); rsRes = stmt.executeQuery(sqlFinalSql);
난 그냥 SQL 쿼리에 대한 문자열 템플릿 포맷 장치로 사용하기 위해 MessageFormat의 클래스를 사용하여 지점에 도착하는 것이 보통 간단하게 루프 당신은 (동안, 경우) sqlInParam가 동적으로 구축 할 수 알아낼.
-
==============================
13.이렇게하려면 당신은 JDBC 연결 및 / 또는 지원하는 낮은 수준에서 SQL 로깅 것을 드라이버가 필요합니다.
이렇게하려면 당신은 JDBC 연결 및 / 또는 지원하는 낮은 수준에서 SQL 로깅 것을 드라이버가 필요합니다.
log4jdbc를 살펴 보자
from https://stackoverflow.com/questions/2382532/how-can-i-get-the-sql-of-a-preparedstatement by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 한 행에 여러 행을 집계 오라클 SQL 쿼리가 있습니까? [복제] (0) | 2020.03.16 |
---|---|
[SQL] SQL 구문의 경우 민감한인가? (0) | 2020.03.16 |
[SQL] SQL IN 절 1000 항목 제한 (0) | 2020.03.16 |
[SQL] 오라클 SELECT TOP 10 기록 (0) | 2020.03.16 |
[SQL] IN 대 또는 WHERE 절 SQL에 (0) | 2020.03.16 |