Pregunta

Estoy planeando reemplazar los objetos Statement repetidamente ejecutados con objetos PreparedStatement para mejorar el rendimiento. Estoy usando argumentos como la función MySQL now () y variables de cadena.

La mayoría de las consultas de PreparedStatement que he visto contenían valores constantes (como 10 , y cadenas como " Nueva York " ) como argumentos utilizado para el ? en las consultas. ¿Cómo podría utilizar las funciones como now () y las variables como argumentos? ¿Es necesario usar el ? s en las consultas en lugar de los valores reales? Estoy bastante confundido.

¿Fue útil?

Solución

Si tienes variables, usa '?'

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

Produce una declaración de sql que parece:

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

Otros consejos

Si tiene una variable que proviene de la entrada del usuario, ¿es esencial que use la? En lugar de concatenar las cuerdas. Los usuarios pueden ingresar una cadena de manera maliciosa, y si la coloca directamente en SQL, puede ejecutar un comando que no tenía la intención.

Me doy cuenta de que este está sobreutilizado, pero lo dice perfectamente:

Little Bobby Tables

No tiene que usar marcadores de posición en una declaración preparada. Algo como:

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

funcionaría bien Sin embargo, no puede usar un marcador de posición y luego vincular una llamada de función a él. Algo como esto no se puede usar para llamar a la función sysdate:

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

Si está llamando a las funciones integradas de su servidor SQL, use PreparedStatement .

Si está llamando a procedimientos almacenados que se han cargado en su servidor SQL, use CallableStatement .

Utilice los signos de interrogación como marcadores de posición para los parámetros de función / procedimiento que está pasando y la función devuelve los valores que está recibiendo.

He desarrollado una función que te permite usar parámetros con nombre en tus consultas 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;
    }

Puedes usarlo de esta manera:

Map<String, Object> pars = new HashMap<>();
pars.put("name", "O'Really");
String sql = "SELECT * FROM TABLE WHERE NAME = :name";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top