Как работает PreparedStatement Java?

Я планирую заменить повторно выполненные объекты Statement объектами PreparedStatement для повышения производительности. Я использую такие аргументы, как функция MySQL now() и строковые переменные.

Большинство запросов PreparedStatement я видел, содержали постоянные значения (например, 10 и строки типа "New York" ) в качестве аргументов, используемых для ? в запросах. Как я могу использовать функции, подобные now() , и переменные в качестве аргументов? Нужно ли использовать ? s в запросах вместо фактических значений? Я совершенно смущен.

Если у вас есть переменные, используйте ‘?’

 int temp = 75; PreparedStatement pstmt = con.prepareStatement( "UPDATE test SET num = ?, due = now() "); pstmt.setInt(1, temp); pstmt.executeUpdate(): 

Создает статус sql, который выглядит так:

 UPDATE test SET num = 75, due = now(); 

Если у вас есть переменная, которая поступает с пользовательского ввода, важно, чтобы вы использовали? а не конкатенировать струны. Пользователи могут ввести строку злонамеренно, и если вы поместите строку прямо в SQL, она может запустить команду, которую вы не намеревались.

Я понимаю, что это слишком злоупотребление, но оно прекрасно говорит:

Маленькие таблички Бобби

Вам не нужно использовать заполнители в PreparedStatement. Что-то вроде:

 PreparedStatement stmt = con.prepareStatement("select sysdate from dual"); 

будет работать нормально. Однако вы не можете использовать местозаполнитель, а затем привязать вызов функции к нему. Что-то вроде этого нельзя использовать для вызова функции sysdate:

 PreparedStatement stmt = con.prepareStatement("select ? from dual"); stmt.setSomethingOrOther(1, "sysdate"); 

Если вы вызываете встроенные функции вашего SQL-сервера, используйте PreparedStatement .

Если вы вызываете хранимые процедуры, которые были загружены на ваш SQL-сервер, используйте CallableStatement .

Используйте вопросительные знаки в качестве заполнителей для параметров функции / процедуры, которые вы передаете, и возвращаемых значений функции, которые вы получаете.

Я разработал функцию, которая позволяет использовать именованные параметры в ваших SQL-запросах:

 private PreparedStatement generatePreparedStatement(String query, Map parameters) throws DatabaseException { String paramKey = ""; Object paramValue = null; PreparedStatement statement = null; Pattern paramRegex = null; Matcher paramMatcher = null; int paramIndex = 1; try { //Create the condition paramRegex = Pattern.compile("(:[\\d\\w_-]+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); paramMatcher = paramRegex.matcher(query); statement = this.m_Connection.prepareStatement(paramMatcher.replaceAll("?"), ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); //Check if there are parameters paramMatcher = paramRegex.matcher(query); while (paramMatcher.find()) { paramKey = paramMatcher.group().substring(1); if(parameters != null && parameters.containsKey(paramKey)) { //Add the parameter paramValue = parameters.get(paramKey); if (paramValue instanceof Date) { statement.setDate(paramIndex, (java.sql.Date)paramValue); } else if (paramValue instanceof Double) { statement.setDouble(paramIndex, (Double)paramValue); } else if (paramValue instanceof Long) { statement.setLong(paramIndex, (Long)paramValue); } else if (paramValue instanceof Integer) { statement.setInt(paramIndex, (Integer)paramValue); } else if (paramValue instanceof Boolean) { statement.setBoolean(paramIndex, (Boolean)paramValue); } else { statement.setString(paramIndex, paramValue.toString()); } } else { throw new DatabaseException("The parameter '" + paramKey + "' doesn't exists in the filter '" + query + "'"); } paramIndex++; } } catch (SQLException l_ex) { throw new DatabaseException(tag.lib.common.ExceptionUtils.getFullMessage(l_ex)); } return statement; } 

Вы можете использовать его так:

 Map pars = new HashMap<>(); pars.put("name", "O'Really"); String sql = "SELECT * FROM TABLE WHERE NAME = :name"; 
Давайте будем гением компьютера.