PreparedStatemet
PREPAREDSTATEMENT:
DEFINICIÓN:
El PreparedStatement nos permite definir una
sentencia SQL base, que nos sirve para modificar/insertar/buscar uno o varios
registros con sólo cambiar los valores de los parámetros que especifiquemos. La
definición de PreparedStatement es una sentencia SQL precompilada para ser ejecutada muchas veces. Pero
al crear el PreparedStatement cada vez, se está precompilando y ejecutando.
Perdiendo completamente la ventaja en rendimiento que supone el precompilado de
una sentencia SQL. Hay algunos manejadores que inclusive crean un procedimiento
almacenado temporal, cada vez que se crea un PreparedStatement.
La interfaz PreparedStatement hereda
de Statement y difiere de esta en dos maneras.
·
Las instancias de PreparedStatement contienen
una sentencia SQL que ya ha sido compilada. Esto es lo que hace que se le llame
‘preparada’.
·
La sentencia SQL contenida en un
objeto PreparedStatement pueden tener uno o más parámetros IN.
Un parámetro IN es aquel cuyo valor no se especifica en la sentencia SQL cuando
se crea. En vez de ello la sentencia tiene un interrogante como un ‘ancla’ para
cada parámetro IN. Debes suministrar un valor para cada interrogante mediante
el método apropiado, que puede ser: setInt, setString,
etc, antes de ejecutar la sentencia creada por el método PreparedStatement, un
objeto de este tipo se usa para sentencias SQL que se toman uno o más
parámetros como argumentos de entrada. Prepared Statement tiene un grupo de
métodos que fijan los valores de los parámetros IN, los cuales son enviados a
la base de datos cuando se procesa la sentencia SQL. Las instancias del
preparedStatement se extienden, es decir heredan del Statement y por tanto
heredan los métodos de Statement. Un objeto PreparedStatement es potencialmente
más eficiente que un objeto Statement porque este ha sido precompilado y
almacenado para su uso futuro.
Son muy útiles cuando una sentencia SQL
se ejecuta muchas veces cambiando solo de algunos valores.
·
Se utiliza para enviar sentencias SQL precompiladas con uno o más
parámetros.
·
Se crea un objeto PreparedStatement
especificando la plantilla y los lugares donde irán.
METODO
EXECUTEUPDATE():
Ejecuta la instrucción SQL determinada, que puede ser una
instrucción INSERT, UPDATE o DELETE; o una instrucción SQL que no devuelve
nada, como una instrucción DDL de SQL. Desde el controlador JDBC 3.0 de
MicrosoftSQL Server, executeUpdate devolverán el número correcto de filas
actualizado en una operación MERGE.
· Sintaxis: public int executeUpdate(java.lang.String sql) .
USO DE CALLABLESTATEMENT:
Un objeto
CallableStatement provee de una forma estándar de llamar a procedimientos
almacenados de la base de datos. Un procedimiento almacenado se encuentra en la
base de datos. La llamada al procedimiento es lo que contiene el objeto
CallableStatement. Esta llamada se escribe en una sintaxis de escape que puede
tomar una de dos formas: un formato con un parámetro resultado y el otro sin él.
Un parámetro resultado, un tipo de parámetro OUT, es el valor devuelto por el
procedimiento almacenado. Ambos formatos pueden tener un número variable de
parámetros de entrada (parámetros IN), de salida (parámetros OUT) o ámbos
(parámetros INOUT). Un interrogante sirve como ‘anclaje’ para cada parámetro.
La sintaxis para invocar un procedimiento almacenado
en JDBC se muestra a continuación: Notar que los corchetes indican que lo que
se encuentra contenido en ellos es opcional, no forma parte de la sintaxis.
{call procedure_name[(?, ?, ...)]}
La sintaxis para un procedimiento que devuelve un
resultado es:
{? = call procedure_name[(?, ?, ...)]}
La sintaxis para un procedimiento almacenado sin
parámetros se parece a algo como:
{call procedure_name}
Normalmente, alguien
que crea un objeto CallableStatement debería saber si la DBMS que está usando
soporta o no procedimientos almacenados y que son estos. Si alguien necesita
chequearlo de cualquier modo, existen varios métodos de DatabaseMetaData que
suministran tal información. Por ejemplo, el método supportsStoredProcedures
devolverá true si la DBMS soporta llamadas a procedimientos almacenados y el
método getProcedures devolverá una descripción de los procedimientos
almacenados disponibles. CallableStatement hereda los métodos de Statement, los
cuales tratan sentencias SQL en general, y también hereda los métodos de
PreparedStatement, que tratan los parámetros IN. Todos los métodos definidos
para CallableStatement tratan los parámetros OUT o los aspectos de salida de
los parámetros INOUT.
Registro de
los tipos JDBC (tipos genéricos SQL) de los parámetros OUT, recuperación de
valores desde ellos o chequear si el valor devuelto es un JDBC NULL.
·
Crear
objetos CallableStatement:
Los objetos CallableStatement se crean con el método prepareCall de
Connection. El siguiente ejemplo crea una instancia de CallableStatement que
contiene una llamada al procedimiento almacenado getTestData, con dos
argumentos y no devuelve resultados.
CallableStatement cstmt = con.prepareCall(
"{call getTestData(?, ?)}");
"{call getTestData(?, ?)}");
Donde los encajes ‘?’ son parámetros IN, OUT ó INOUT
dependiendo del procedimiento getTestData.
·
Parámetros
IN y OUT:
El paso de valor para cualquier parámetro IN de un
objeto CallableStatement se realiza mediante los métodos setXXX heredados de
PreparedStatement. El tipo del valor a pasar se determina por el método setXXX
a usar (setFloat para pasar un valor float, y así).
Si el procedimiento almacenado devuelve parámetros OUT, el tipo JDBC de
cada parámetro OUT debe ser registrado antes de que el objeto CallableStatement
sea ejecutado (Esto es necesario porque algunas DBMS necesitan el tipo JDBC).
El registro del tipo JDBC se realiza mediante el método registerOutParameters.
Después que la sentencia ha sido ejecutada, los métodos getXXX de
CallableStatement recuperan los valores de los parámetros. El método correcto
getXXX a usar es el tipo Java que corresponde al tipo JDBC registrado para el
parámetro. En otras palabras, registerOutParameter usa un tipo
JDBC (por tanto, coincide con el tipo con el tipo JDBC que la base de datos devolverá) y getXXX ‘casts’ este a un tipo Java.
JDBC (por tanto, coincide con el tipo con el tipo JDBC que la base de datos devolverá) y getXXX ‘casts’ este a un tipo Java.
Para ilustrar
esto, el siguiente ejemplo registra los parámetros OUT, ejecuta el
procedimiento almacenado llamado por cstmt y recupera los valores devueltos en
los parámetros OUT. El método getByte recupera un byte Java del primer
parámetro, y getBigDecimal recupera un objeto BigDecimal (con tres dígitos
después del punto decimal) del segundo parámetro OUT:
CallableStatement cstmt = con.prepareCall(
"{call getTestData(?, ?)}");
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
cstmt.executeQuery();
byte x = cstmt.getByte(1);
java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
"{call getTestData(?, ?)}");
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
cstmt.executeQuery();
byte x = cstmt.getByte(1);
java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
De modo distinto a ResultSet, CallableStatement no
tiene un mecanismo especial para recuperar grandes valores OUT
incrementalmente.
·
Parámetros
INOUT:
Son parámetros que suministran entradas así como
aceptan salidas. Estos requieren llamar a los métodos apropiados setXXX
(heredados de PreparedStatement) además de llamar al método
registerOutParameter. Los métodos setXXX fijan los valores como parámetros de
entrada y registerOutParameter registra sus tipos JDBC como parámetros de
salida. El método setXXX suminstra un valor Java que el driver convierte en un
valor JDBC antes de enviarlo a la base de datos.
El tipo JDBC del valor IN y el tipo JDBC para
suminstrado al método registerOutParameter debe ser el mismo. Luego, para
recuperar el valor de salida, se usa el método apropiado getXXX. Por ejemplo,
un parámetro cuyo tipo Java es byte debería usar el método setByte para asignar
el valor de entrada, debería suplir un TINYINT como tipo JDBC para
registerOutParameter, y debería usar getByte para recuperar el valor de salida
(Sección 8, da más información y contiene tablas de tipos mapeados).
El siguiente ejemplo asume que existe un
procedimiento almacenado reviseTotal con un único parámetro INOUT. El método
setByte fija el valor del parámetro a 25 que es el que el driver enviará a la
base de datos como un JDBC TINYINT. Después registerOutParameter registrará el
parámetro como un JDBC TINYINT. Luego que el procedimiento sea ejecutado se
devolverá un nuevo JDBC TINYINT y el método getByte lo recuperará como un nuevo
valor byte Java.
CallableStatement cstmt = con.prepareCall(
"{call reviseTotal(?)}");
cstmt.setByte(1, 25);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);
"{call reviseTotal(?)}");
cstmt.setByte(1, 25);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);
·
Recuperar
parámetros OUT después de resultados.
Dadas las limitaciones impuestas por algunas DBMS, se recomienda en aras
de la máxima portabilidad, que todos los resultados generados por la ejecución
de un objeto CallableStatement deberían recuperarse antes que los parámetros
OUT usando los métodos CallableStatement.getXXX.
Si un objeto CallableStatement devuelve múltiples objetos ResultSet
(mediante una llamada al método execute), todos los resultados deben
recuperarse antes que los parámetros OUT. En este caso, debe asegurarse de que
todos los resultados han sido accedidos, los métodos de Statement getResultSet,
getUpdateCount y getMoreResults necesitan ser llamados hasta que no haya más
resultados.
Después de hecho esto, los valores de los parámetros
OUT pueden ser recuperados mediante los métodos CallableStatement.getXXX.
·
Recuperar
valores NULL en parámetros OUT:
El valor devuelto en un parámetro OUT puede ser JDBC
NULL. Cuando esto ocurre, le valor JDBC NULL se convertirá de forma que el
valor devuelto por el método getXXX sea null, 0 o false dependiendo del tipo
del método getXXX usado. Como con los objetos ResultSet, la única manera de
saber si un valor de 0 o false fue originalmente NULL JDBC es testear el método
wasNull, que devuelve true si el último valor leído por un método getXXX fue
JDBC NULL y false en caso contrario. La sección 5 contiene más información al
respecto.
EJEMPLOS:
Un ejemplo típico es:
PreparedStatement pstmt = con.prepareStatement(
"update empleado set sueldo = ? where id_empleado = ?");
pstmt.setDouble(1, 153833.00);
pstmt.setInt(2, 110592);
Esto nos permite tener una
sentencia SQL de fácil lectura y sin tener que concatenar cadenas o hacer
conversiones de tipos. De la documentación de java:
Objeto que representa una instrucción SQL precompilada. Una instrucción SQL se precompila y se almacena en un objeto PreparedStatement. Este objeto puede utilizarse para ejecutar esta sentencia de forma eficiente varias veces.Supongamos que tenemos un mapa de empleados y sueldos:
Objeto que representa una instrucción SQL precompilada. Una instrucción SQL se precompila y se almacena en un objeto PreparedStatement. Este objeto puede utilizarse para ejecutar esta sentencia de forma eficiente varias veces.Supongamos que tenemos un mapa de empleados y sueldos:
Map<Integer, Double> empleadoSueldo = new HashMap<>();
empleadoSueldo.put(1, 1000.0);
empleadoSueldo.put(2, 2000.0);
empleadoSueldo.put(3, 3000.0);
Es muy común ver un código como el siguiente:
for(Map.Entry<Integer, Double> empleado :
empleadoSueldo.entrySet()) {
PreparedStatement pstmt =
con.prepareStatement(
"update empleado set
sueldo = ? where id_empleado = ?");
pstmt.setDouble(1,
empleado.getValue());
pstmt.setInt(2,
empleado.getKey());
pstmt.executeUpdate();
}
Ejemplo de PreparedStatement de consulta:
Por ejemplo, supongamos que hay un campo de texto en el que el usuario
puede introducir su dirección de correo electrónico y con este dato se desea
buscar al usuario:
Connection con = DriverManager.getConnection(url);
String consulta = "SELECT usuario FROM registro WHERE email like ?";
PreparedStatement pstmt = con.prepareStatement(consulta);
pstmt.setString(1 , campoTexto.getText());
ResultSet resultado = ps.executeQuery();
String consulta = "SELECT usuario FROM registro WHERE email like ?";
PreparedStatement pstmt = con.prepareStatement(consulta);
pstmt.setString(1 , campoTexto.getText());
ResultSet resultado = ps.executeQuery();
Ejemplo de PreparedStatement de modificación:
En el siguiente ejemplo se va a insertar un nuevo registro en una tabla:
Connection con = DriverManager.getConnection(url);
String insercion = "INSERT INTO registro(usuario , email , fechaNac) values ( ? , ? , ? )");
PreparedStatement pstmt = con.prepareStatement(consulta);
String user = . . . ;
String email = . . . ;
Date edad = . . . ; //O int edad;
pstmt.setString(1 , user);
pstmt.setString(2 , email);
pstmt.setDate(3 , edad); // setInt(3, edad);
ps.executeUpdate();
String insercion = "INSERT INTO registro(usuario , email , fechaNac) values ( ? , ? , ? )");
PreparedStatement pstmt = con.prepareStatement(consulta);
String user = . . . ;
String email = . . . ;
Date edad = . . . ; //O int edad;
pstmt.setString(1 , user);
pstmt.setString(2 , email);
pstmt.setDate(3 , edad); // setInt(3, edad);
ps.executeUpdate();
Como los objetos PreparedStatement están
precompilados, su ejecución es más rápida que los objetos Statement.
Consecuentemente, una sentencia SQL que se ejecute muchas veces a menudo se
crea como PreparedStatement para incrementar su eficacia.
Siendo una
subclase de Statement, PreparedStatement, como ya se ha
mencionado hereda toda la funcionalidad de Statement. Además, se
añade un conjunto completo de métodos necesarios para fijar los valores que van
a ser enviados a la base de datos en el lugar de las ‘anclas’ para los
parámetros IN.
También se
modifican los tres métodos execute, executeQuery y executeUpdate de
tal forma que no toman argumentos. Los formatos de Statement de
estos métodos (los formatos que toman una sentencia SQL como argumento) no
deberían usarse nunca con objetos PreparedStatement, a pesar de
estar disponibles para ellos.
RESUMEN:
PreparedStatement
es un objeto sumamente importante ya que nos permite definir una sentencia SQL
base, nos sirve para modificar/insertar/buscar uno o varios registros con sólo
cambiar los valores de los parámetros que especifiquemos. PreparedStatement es
una sentencia SQL precompilada para ser ejecutada muchas veces. Pero
al crear el PreparedStatement cada vez, se está precompilando y ejecutando.
Perdiendo completamente la ventaja en rendimiento que supone el precompilado de
una sentencia SQL. Hay algunos manejadores que inclusive crean un procedimiento
almacenado temporal, cada vez que se crea un PreparedStatement.
SUMMARY:
PreparedStatement
is an extremely important object since it allows us to define a base SQL
statement, it is used to modify / insert / search one or more registers by
simply changing the values of the parameters that we specify. PreparedStatement
is a precompiled SQL statement to be executed many times. But when creating the
PreparedStatement every time, it is being precompiled and executed. Completely
losing the performance advantage of precompiling an SQL statement. There are
some handlers that even create a temporary stored procedure, every time a
PreparedStatement is created.
RECOMENDACIONES:
· Si escribe una sentencia SQL que se va a utilizar más de una vez,
el rendimiento será mayor si la sentencia es un objeto PreparedStatement.
· Cada vez que se ejecuta una sentencia, se realiza un proceso de
dos pasos: la sentencia se prepara y luego se procesa.
·
Debido a la mejora de rendimiento
que proporcionan las sentencias PreparedStatement, conviene utilizarlas en el
diseño de las aplicaciones siempre que sea posible.
CONCLUSIONES:
En conclusión,
debemos usar consultas parametrizadas con PreparedStatement. Esto reduce la carga en la base de datos
permitiéndole reutilizar planes de acceso que ya estaban preparados. Esta caché
es de toda la base de datos, por lo que, si puede organizar todas sus
aplicaciones para utilizar SQL parametrizado similar, mejorará la eficiencia de
este esquema de almacenamiento en caché como una aplicación puede aprovechar
las instrucciones preparadas utilizadas por otra aplicación.
Por último, el uso
correcto de PreparedStatement también le permite aprovechar la caché de
instrucciones preparadas en el servidor de aplicaciones. Esto mejora el
rendimiento de su aplicación, ya que la aplicación puede reducir el número de
llamadas al controlador JDBC mediante la reutilización de una llamada de
sentencia previamente preparada.
Si utiliza
sentencias preparadas parametrizadas, mejora la eficiencia de la base de datos
y del código alojado de su servidor de aplicaciones. Ambas mejoras permitirán
que su aplicación mejore su rendimiento.
·
Las sentencias de
SQL en objetos PreparedStatement se precompilan en el lado del servidor de
bases de datos.
·
Los parámetros IN
se admiten en sentencias SQL en objetos PreparedStatement.
·
Los métodos setXXX
() se pueden usar para proporcionar valores a los parámetros en los objetos
PreparedStatement.
·
Se admite el modo
de ejecución por lotes para ejecutar la sentencia SQL de ejecución varias veces
en una sola transacción.
·
Para múltiples
operaciones de inserción de repetición, PreparedStatement realiza mejor que la
instrucción INSERT normal.
APRECIACIÓN DEL EQUIPO:
Como
futuros ingenieros de Sistemas es sumamente importante saber manejar el
lenguaje de programación Java por los múltiples beneficios, entonces mediante
su estudio podemos conocer su estructura y sobretodo como podemos acceder a una
Base de Datos desde la plataforma Java, para eso en este tema podemos conocer
cómo desarrollar el objeto PreparedStatement ya que viene a ser una sentencia SQL de base de
datos precompilada, y al estar precompilada, su ejecución será más rápida que
una SQL normal, por lo que es adecuada cuando vamos a ejecutar la misma
sentencia SQL (con distintos valores) muchas veces.
GLOSARIO DE TÉRMINOS:
·
Compilar: Un compilador es un programa informático que
traduce un programa escrito en un lenguaje de programación a otro lenguaje
diferente. Usualmente el segundo lenguaje es lenguaje de máquina, pero también
puede ser un código intermedio (bytecode), o simplemente texto. Este proceso de
traducción se conoce como compilación.
·
Merge: Significa unir.
·
Anclaje: Un ancla o anclaje es el inicio y el destino de cada enlace. De forma más precisa, un anclaje
es el punto de activación o punto de destino de un enlace. Ambos puntos, el punto de activación y el punto de
destino del enlace, reciben el nombre de anclajes.
·
Invocar:
Una invocación o llamada función implica pasarle el control de la
ejecución del programa, así como los argumentos o parámetros que requiere para
realizar su tarea, se realiza colocando el nombre de la función y los
argumentos actuales en el mismo orden que los parámetros formales
correspondientes.
·
DBMS: Database management system (DBMS), es un conjunto de programas
que se encargan de manejar la creación y todos los accesos a las bases de
datos, está compuesto por:
DDL: Lenguaje de
Definición de Datos
DML: Lenguaje de Manipulación de Datos
SQL: Lenguaje de Consulta.
DML: Lenguaje de Manipulación de Datos
SQL: Lenguaje de Consulta.
LINKOGRAFÍA:
·
http://seduca.uaemex.mx/material/LIA/POO/materiales/PreparedStatement.html
·
https://msdn.microsoft.com/es-es/library/ms378630(v=sql.110).aspx
·
http://preparedstatement.blogspot.pe/2016/03/definicion-preparedstatement-dice-que.html
·
http://seduca.uaemex.mx/material/LIA/POO/materiales/PreparedStatement.html
·
http://www.euskalnet.net/jaoprogramador/j2ee/JDBC/jdbc25.htm
· http://www.herongyang.com/JDBC/Derby-PreparedStatement.html
https://www.youtube.com/watch?v=MWs-YwgE7Qc
· http://es.slideshare.net/LisbethOcaaBueno/prepared-statement-69819972
Comentarios
Publicar un comentario