Как работает Java PreparedStatement? - PullRequest
5 голосов
/ 07 января 2009

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

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

Ответы [ 5 ]

11 голосов
/ 07 января 2009

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

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

Little Bobby Tables

9 голосов
/ 07 января 2009

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

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

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

UPDATE test SET num = 75, due = now();
0 голосов
/ 10 декабря 2013

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

private PreparedStatement generatePreparedStatement(String query, Map<String, Object> 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<String, Object> pars = new HashMap<>();
pars.put("name", "O'Really");
String sql = "SELECT * FROM TABLE WHERE NAME = :name";
0 голосов
/ 11 января 2009

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

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

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

0 голосов
/ 08 января 2009

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

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

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

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