Это означает, что указанная переменная не указана ни на что. Я мог бы сгенерировать это так:
SqlConnection connection = null;
connection.Open();
Это вызовет ошибку, потому что, пока я объявил переменную «connection
», она не указала ни на что. Когда я пытаюсь вызвать член «Open
», для его устранения нет ссылки, и он будет вызывать ошибку.
Чтобы избежать этой ошибки:
object == null
. Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам ввести нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.
Используя подготовленные инструкции, нет «SQL-запроса»:
Но не существует пересоздания реального реального SQL-запроса - ни на стороне Java, ни на стороне базы данных.
Итак, нет способа получить SQL-код подготовленного оператора, поскольку такой SQL нет.
Для цели отладки решения должны быть либо:
Это нигде не определено в контракте API JDBC, но если вам повезет, драйвер JDBC, о котором идет речь, может вернуть полный SQL, просто позвонив PreparedStatement#toString()
. I.e.
System.out.println(preparedStatement);
По крайней мере MySQL 5.x и PostgreSQL 8.x поддерживают JDBC-драйверы. Однако большинство других драйверов JDBC его не поддерживают. Если у вас есть такой, то лучше всего использовать Log4jdbc или P6Spy .
В качестве альтернативы вы также можете написать общую функцию, которая принимает значение Connection
, строку SQL и значения оператора и возвращает PreparedStatement
после регистрации строки SQL и значений. Пример Kickoff:
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
, который обертывает (украшает) real PreparedStatement
по построению и переопределяет все методы, чтобы он вызывал методы real PreparedStatement
и собирал значения во всех методах setXXX()
и лениво конструировал «фактическую» строку SQL когда вызывается один из методов executeXXX()
(довольно много работы, но большинство IDE обеспечивает автогенераторы для методов декоратора, Eclipse делает). Наконец, просто используйте его. Это также в основном то, что P6Spy и супруги уже делают под капотами.
logger.debug(sql + " " + Arrays.asList(values))
. Я ищу способ зарегистрировать оператор sql с уже интегрированными в него параметрами. Без зацикливания и замены вопросительных знаков.
– froadie
4 March 2010 в 22:11
PreparedStatement
каждый раз. Разве это не так-то эффективно, поскольку цель PreparedStatement
состоит в том, чтобы создать их один раз и повторно использовать их повсюду?
– Bhushan Patil
9 March 2017 в 05:41
Я использую Oralce 11g и не смог получить окончательный SQL из PreparedStatement. После прочтения @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);
Вы понимаете, что sqlInParam может быть динамически построена в цикле (for while). Я просто упростил доступ к тому, чтобы использовать класс MessageFormat для использования в качестве шаблонный шаблон строки для SQL-запроса.
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
– latj
31 May 2017 в 20:23
Если вы выполняете запрос и ожидаете ResultSet
(по крайней мере, в этом сценарии), вы можете просто вызвать ResultSet
's getStatement()
следующим образом:
ResultSet rs = pstmt.executeQuery();
String executedQuery = rs.getStatement().toString();
Переменная executedQuery
будет содержать инструкцию, которая использовалась для создания ResultSet
.
Теперь, я понимаю, этот вопрос довольно старый, но я надеюсь, что это кому-то поможет ..
Фрагмент кода для преобразования 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;
}
Просто функция:
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;
}
Хорошо, что и для подготовленногоStatement.
.toString()
с несколькими дополнительными строками, чтобы обмануть беспроигрышных пользователей и уже ответили давным-давно.
– Pere
8 February 2018 в 18:24
Если вы используете MySQL, вы можете регистрировать запросы с помощью журнала запросов MySQL . Я не знаю, предоставляют ли другие поставщики эту функцию, но, скорее всего, они делают.
Я использую Java 8, драйвер JDBC с соединителем MySQL v. 5.1.31.
Я могу получить реальную строку 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());
Итак, это возвращает smth следующим образом:
INSERT INTO oc_manufacturer SET manufacturer_id = 23, name = 'Google', sort_order=0;
Я извлек свой sql из PreparedStatement, используя prepareStatement.toString () В моем случае toString () возвращает String следующим образом:
org.hsqldb.jdbc.JDBCPreparedStatement@7098b907[sql=[INSERT INTO
TABLE_NAME(COLUMN_NAME, COLUMN_NAME, COLUMN_NAME) VALUES(?, ?, ?)],
parameters=[[value], [value], [value]]]
Теперь я создал метод (Java 8), который использует regex для извлечения как запроса, так и значений и помещает их в карту:
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());
Если ваш подготовленныйStatement.toString () отличается от моего случая, это просто вопрос «корректировки» регулярного выражения.
Для этого вам нужно подключение JDBC и / или драйвер, который поддерживает ведение журнала sql на низком уровне.
Взгляните на log4jdbc
Я применил следующий код для печати SQL из PrepareStatement
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[" + "] ...");
}
}
Очень поздно :), но вы можете получить исходный SQL из OraclePreparedStatementWrapper с помощью
((OraclePreparedStatementWrapper) preparedStatement).getOriginalSql();