Statement, PreparedStatement y CallableStatement

java jdbcEn Java JDBC me entró la duda entre Statement, PreparedStatement y CallableStatement. Entre los dos primeros lo tenía claro, pero no tenía muy clara la diferencia entre los dos segundos. Asi que aquí va un resumen de los tres, ventajas e inconvenientes de cada uno y cuando deben usarse.

Statement es la base. Pones la sentencia SQL y la ejecutas. Tiene varias pegas:

  • Cada vez que ejecutas la sentencia, tiene que «compilarla», es decir, revisar la sintaxis que es correcta y ejecutarla. Por ello, no es eficiente si vas a ejecutar la misma sentencia SQL varias veces.
  • La cadena SQL se compone como un String normal. Si usas variables para componer la cadena, tienes que revisar el contenido de esas variables para evitar la SQL injection. Dicho de otra forma, si en tu SQL vas a insertar una columna tipo String con un valor que ha introducido un usuario a mano, tendras en tu código java algo como esto
    «INSERT INTO tabla (nombre) VALUES (‘ » + variable +» ‘)»
    bien así, bien con cualquier otro mecanismo de concatenación de cadenas. ¿Qué pasa si la variable contiene una comilla sencilla igual a la que se usa para delimitar los String en SQL. Pues sí, error al canto, la cadena se cierra antes de lo esperado y el resto de la sentencia SQL no tiene sentido
  • Con este tipo de composición con String de java, no se puede o es muy difícil meter bytes en una columna tipo BLOB o similar.

¿Cuando es útil entonces Statement?. Para sentencias sencillas que solo vamos a usar una vez. Ejemplo típico son la creación o update de las tablas cuando arrancamos nuestra aplicación o algún SELECT al inicio de la aplicación para verificar algo, como el número de versión de las tablas.

PreparedStatement hereda de Statement y le añade ciertas ventajas.

  • Compila el SQL que le pasamos. Así que si lo ejecutamos varias veces, es más eficiente.
  • La SQL se escribe con un String, pero poniendo ? en el lugar donde van las variables. Algo como
    «INSERT INTO tabla(nombre) VALUES (?)»
    no ponemos comillas simples en ningún caso, sea el tipo que sea la columna. Luego PreparedStatement tiene métodos para rellenar esos valores y se encarga él de «escapar» los posibles caracters extraños, por lo que no es posible la SQL injection.
  • Sí se pueden meter arrays de bytes o incluso «flujos» (Stream) de bytes, para no tener que tener todos los bytes todos cargados en memoria y pasarlos de golpe.

Así que PreparedStatement debe ser nuestra opción por defecto salvo quizás los casos que hemos comentado arriba en que Statement es útil. Y los casos que comentarmos a continuación para un CallableStatement.

CallableStatement hereda de PreparedStatement, por lo que tiene todas sus ventajas, pero añade una ventaja adicional

  • Tiene una sintaxis propia, no SQL, para la llamada a procedimientos y funciones de base de datos. Para que sepa que estamos usando esa sintaxis especial y no la específica del SQL de la base de datos concreta que estemos usando, debemos ponerlo entre llaves, así
    «{call un_procedimiento (?,?) }»
    «{? = call una_funcion (?,?,?}»
    por supuesto, con los parámetros que necesitemos puestos como interrogantes. Si no hay parámetros, no hace falta el paréntesis

Así que CallableStatement tiene todas las ventajas de PreparedStatement, pero además nos aisla de la sintaxis específica de nuestra base de datos para la llamada a procedimientos o funciones. Es adecuado por tanto para este tipo de llamadas.

Entradas relacionadas:

Esta entrada ha sido publicada en java y etiquetada como , . Guarda el enlace permanente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.