1: CONTENIDO.
DEFINICION.
Java
Data base Connectivity, más conocida por sus siglas JDBC,es una API que permite la ejecución de
operaciones sobre bases de datos desde
el lenguaje de
programación Java, independientemente del sistema operativo donde se
ejecute o de la base de datos a la cual se accede, utilizando el dialecto SQL
del modelo de base de datos que se utilice.
El
API JDBC se presenta como una colección de interfaces Java y métodos de gestión de manejadores de
conexión hacia cada modelo específico de base de datos. Un manejador de conexiones
hacia un modelo de base de datos en particular es un conjunto de clases que implementan las interfaces Java y que utilizan los métodos de registro
para declarar los tipos de localizadores a base de datos (URL)
que pueden manejar. Para utilizar una base de datos particular, el usuario
ejecuta su programa junto con la biblioteca de conexión apropiada al modelo de
su base de datos, y accede a ella estableciendo una conexión; para ello provee
el localizador a la base de datos y los parámetros de conexión específicos. A partir
de allí puede realizar cualquier tipo de tarea con la base de datos a la que
tenga permiso: consulta, actualización, creación, modificación y borrado de
tablas, ejecución de procedimientos en
la base de datos, etc.
OBJETOS CONNECTION,
STATEMENT Y RESULTSET:
ü CONNECTION: Un objeto Connection se
utiliza para representar enlaces de comunicación entre sistemas CICS. Con el
fin de direccionar el trabajo de un sistema CICS a otro, debe definirse un par
de objetos Connection. Cada mitad del par Connection se asocia con un objeto
SystemClone, que es el sistema CICS a partir del cual se define la conexión.
Las dos conexiones de cada mitad deben estar relacionadas entre sí de modo que
WLM de CICS pueda detectar que ambas partes de la relación están presentes y
son correctas. Una relación se define a partir de la conexión de una parte del
par con la otra parte. No es necesario codificar la relación inversa, ya que
WLM de CICS la detecta. Con el fin de posibilitar el direccionamiento a través
de un objeto Connection, ambas mitades de la conexión deben definirse como
activas (en servicio). Es posible establecer el atributo In Service para una
mitad de la conexión en cero. En tal caso, el trabajo no se direcciona a la
región porque el programa de utilidad WLM de CICS no ve que exista una vía de
acceso de comunicación segura a la misma.
Las entradas creadas para los objetos
Connection del archivo de configuración de WLM de CICS no reemplazan ni afectan
a las Definiciones de comunicaciones de CICS. El programa de utilidad de WLM de
CICS utiliza las entradas del objeto Connection para crear el modelo de objeto
interno.
Atributos de los
objetos Connection
Los objetos Connection tienen valores
de atributo para describir el coste de las comunicaciones mediante el objeto
Connection relativas al coste de utilización de otros objetos Connection en la
configuración. Asimismo, dichos valores indican si el objeto Connection se
encuentra en servicio o no. Tabla 1 muestra los
atributos y valores predeterminados de un objeto Connection.
Tabla 1. Atributos y valores
predeterminados de un objeto Connection
|
||
Atributo
|
Valor predeterminado
|
Descripción
|
load
|
0,1
|
El factor de ponderación se aplica al objeto que utiliza esta
conexión. El incremento de este número desviará el algoritmo WLM del sistema
conectado.
|
inService
|
0
|
Se habilita un conmutador para especificar si este objeto Connection
se encuentra actualmente habilitado (1) o no (0). Tenga en cuenta que ambos
objetos Connection deben estar en servicio (inService) para posibilitar el
direccionamiento entre ambos sistemas.
|
El objeto Connection representa una
conexión HTTP entre la prueba dinámica (el cliente) y el servidor Web. La
prueba abre la conexión, aunque tanto la prueba como el servidor Web pueden
cerrarla. Se pueden enviar múltiples solicitudes mediante una sola conexión,
siempre que esta última permanezca abierta. Propiedades
Propiedad
|
Descripción
|
Comprueba si la
conexión está abierta.
|
|
Obtiene el número
del puerto utilizado por la conexión.
|
|
Obtiene o define
el número de redirecciones de encabezados HTTP que se siguen.
|
Obtiene el nombre
del host o dirección IP del servidor al que está conectado el cliente.
|
|
Comprueba si la
conexión HTTP entre el cliente y el servidor utiliza el protocolo SSL
("https://").
|
Métodos
Método
|
Descripción
|
Cierra la
conexión, si está abierta. No devuelve un error si la conexión ya está
cerrada.
|
|
Envía una
solicitud HTTP al servidor.
|
PROPIEDADES
ConnectionString: Especifica la referencia a la base de datos con la cual queremos
conectar, conteniendo en una cadena de texto la información necesaria para
efectuar esa conexión mediante parejas de valores separadas por ";".
Los valores que podemos asignar son:
Data Source: DSN=Nombre ODBC de la Base de Datos
Usuario: UID=Nombre
de Usuario
Password: PWD=Password
del usuario para la base de datos
Ejemplo:
<%
conexion.ConnectionString="DSN=MIOdbc;UID=pepe;PWD=1234" %>
MODE:
Especifica los permisos de la conexión.
Algunos de los valores más habituales que podemos
asignar son:
1 Establece permiso solo de
Lectura
2 Establece permiso solo de
Escritura
3 Establece permiso de
Lectura/Escritura
Ejemplo:
<% conexion.Mode=3 %>
Métodos:
BeginTrans:
Abre una transacción; todas las operaciones que
realicemos a partir de ese momento no serán efectivas hasta que no cerremos la
transacción.
Ejemplo:
<% conexion.BeginTrans %>
Close:
Cierra el objeto
Ejemplo:
<% conexion.close %>
CommitTrans:
Cierra una transacción haciendo efectivos los
cambios efectuados dentro de ella.
Ejemplo:
<% conexion.CommitTrans %>
Execute:
Ejecuta una sentencia SQL contra la base de datos.
Ejemplo:
<% Set resultado=conexion.execute (Select * from
amigos) %>
Open:
Abre la conexión con los parámetros especificados
en las propiedades.
Ejemplo:
<% conexion.open %>
RollBackTrans:
Deshace todos los cambios efectuados en la base de
datos desde el inicio de la transacción.
Ejemplo:
<% conexion.RollBackTrans %>
ü STATEMENT: Un objeto
Statement se usa para enviar sentencias SQL a la base de datos. Actualmente hay
tres tipos de objetos Statement, todos los cuales actúan como contenedores para
la ejecución de sentencias en una conexión dada: Statement, PreparedStatement que
hereda de Statement y CallableStatement que hereda de PreparedStatement. Estas
están especializadas para enviar tipos particulares de sentencias SQL, Un
objeto Statement se usa para ejecutar una sentencia SQL simple sin parámetros.
Un objeto PreparedStatement se usa para ejecutar sentencias SQL precompiladas
con o sin parámetros IN; y un objeto CallableStatement se usa para ejecutar un
procedimieno de base de datos almacenado.
La interfase Statement suminstra
métodos básicos para ejecutar sentencias y devolver resultados. La interfase
PreparedStatement añade métodos para trabajat con los parámetros IN; y la
interfase CallableStatement añade métodos para trabajar con parameters OUT.
Ejecución de
sentencias usando objetos Statement.
La interfase Statement nos suministra
tres métodos diferentes para ejecutar sentencias SQL, executeQuery,
executeUpdate y execute. El método a usar está determinado por el producto de
la sentencia SQL.
El método executeQuery está diseñado
para sentencias que producen como resultado un único result set tal como las
sentencias SELECT.
El método executeUpdate se usa para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL (Data Definition Language) como CREATE TABLE o DROP TABLE. El efecto de una sentencia INSERT, UPDATE o DELETE es una modificación de una o más columnas en cero o más filas de una tabla. El valor devuelto de executeUpdate es un entero que indica el número de filas que han sido afectadas (referido como update count). Para sentencias tales como CREATE TABLE o DROP TABLE, que no operan sobre filas, le valor devuelto por executeUpdate es siempre cero.
El método executeUpdate se usa para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL (Data Definition Language) como CREATE TABLE o DROP TABLE. El efecto de una sentencia INSERT, UPDATE o DELETE es una modificación de una o más columnas en cero o más filas de una tabla. El valor devuelto de executeUpdate es un entero que indica el número de filas que han sido afectadas (referido como update count). Para sentencias tales como CREATE TABLE o DROP TABLE, que no operan sobre filas, le valor devuelto por executeUpdate es siempre cero.
El método execute se usa para ejecutar sentencias que devuelven más de
un result set, más que un update count o una combinación de ambos. Como es
esta una característica avanzada que muchos programadores no necesitarñan
nunca se verá en su propia sección.
Todos los métodos que ejecutan sentencias cierran los objetos
Resultset abiertos como resultado de las llamadas a Statement. Esto quiere
decir que es necesario completar el proceso con el actual objeto Resulset
antes de reejecutar una sentencia Statement.
Debe notarse que la interfase PreparedStatement, que hereda los
métodos de la interfase Statement, tiene sus propias versiones de los métodos
executeQuery, executeUpdate y execute. Los objetos Statement en sí mismos no
contienen una sentencia SQL, por tanto debe suministrarse como un argumento a
los métodos Statement.execute. Los objetos PreparedStatement no suministran
una sentencia SQL como argumento a estos métodos puesto que ya tienen la
sentencia precompilada. Los objetos CallableStatement heredan las formas de
estos métodos de PreparedStatement. Usar un parametro de query con las
versiones de los métodos de PreparedStatement o CallableStatement producirái
una SQLException.
Algunos DBMS tratan cada sentencia en un procedimiento almacenado como
sentencias separadas. Otros tratan el procedimiento entero como una sentencia
compuesta. Esta diferencia se convierte en importante cuando está activo el
modo auto-commit porque afecta cuando se llama al método commit. En el primer
caso, cada sentencia individual es commitada. En el segundo, se commiten
todas juntas.
Cerrar objetos Statement.
Los objetos Statement se cerrarán automáticamente por el colector de
basura de Java (garbage collector). No obstante se recomienda como una buena
práctica de programación que se cierren explicitamente cuando no sean ya
necesarios. Esto libera recursos DBMS inmediatamente y ayuda a evitar
potenciales problemas de memoria.
Sintaxis de Escape SQL en objetos Statement.
Los objetos Statement pueden contener sentencias SQL que usen sintaxis
de escape SQL. La sintaxis de escape señala al driver que el código que lleva
debe ser tratado diferentemente. El driver buscará por cualquier sintaxis de
escape y lo traducirá en código que entiende la base de datos en particular.
Esto hace que la sintaxis de escape sea independiente de la DBMS y permite al
programador usar características que de otro modo no estarían disponibles.
Una cláusula de escape se enmarca entre llaves y tiene una palabra
clave:
{keyword . . . parameters . . . }
La palabra clave (keyword) indica el tipo de cláusula de escape, según se muestra:
Escape para caracteres LIKE.
Los caracteres “%” y “_” trabajan como wildcards en la cláusula SQL
LIKE (“%” significa cero o más caracteres y “_” significa exactamente un
carácter”. En orden a interpretarlos literalmente, pueden estar precedidos
por un backslash (‘\’), que es un carácter de escape especial en cadenas. Se
puede especificar un carácter que se use como carácter de escape por la
inclusión de la sintaxis siguiente al final de la consulta.
{escape 'escape-carácter'}
Por ejemplo, la siguiente query, usando backslash como carácter de
escape, encuentra nombres de identificador que comiencen con ‘_’.
stmt.executeQuery("SELECT name FROM Identifiers
WHERE Id LIKE `\_%' {escape `\'}; fin para funciones escalares
Casi todas las DBMS tienen funciones numéricas, de cadena, de fecha y
conversión sobre valores escalares. Una de estas funciones puede usarse
colocándola en la sintaxis de escape con la clave fn seguida del nombre de la
función deseada y sus argumentos. Por ejemplo, para llamar a la función
concat con dos argumentos que serán concatenados:
{fn concat("Hot", "Java")};
El nombre del usuario actual de la base de datos puede obtenerse
mediante:
{fn user()};
Las funciones escalares pueden estar soportadas por diferentes DBMS
con ligeras diferencias de sintaxis, y pueden no estar disponibles en todos
los drivers. Varios métodos de DatabaseMetaData nos listarán las funciones
que están soportadas. Por ejemplo, el método getNumericFunctions devuelve una
lista de los nombres de las funciones numéricas separadas por comas, el
método getStringFunction nos devuelve los nombres de las funciones de cadena,
y así varías más.
EL driver o bien mapeará la llamada a la función ‘escapada’ en su
propia sintaxis o implementará la función el mismo.
• d, t y ts para literales de fecha y tiempo
Las DBMS difieren en la sintaxis que usan para los literales de fecha,
tiempo y timestamp. JDBC soporta un formato estándar ISO para estos literales
y usa una clausula de escape que el driver debe traducir a la representación
del DBMS.
Por ejemplo, una fecha se especifica en SQL JDBC mediante la sintaxis:
{d `yyyy-mm-dd'}
En esta sintaxis, yyyy es el año, mm es el mes y dd es el dia. El
driver reemplazará la clausula de escape por la representaciòn propia
equivalente de la DBMS. Por ejemplo, el driver reemplazaría {d 1999-02-28}
por ’28-FEB-99’ si este es el formato apropiado para la base subyacente.
Hay clausulas de escape análogas para TIME y TIMESTAMP
{t `hh:mm:ss'}
{ts `yyyy-mm-dd hh:mm:ss.f . . .'} La parte fraccional de los segundos (.f . . .) del TIMESTAMP puede omitirse.
• call ó ? = call para procedimientos almacenados
Si una database soporta procedimientos almacenados, estos pueden ser
invocados desde JDBC mediante:
{call procedure_name[(?, ?, . . .)]}
o, cuando el procedimiento devuelve como resultado un parámetro
{? = call procedure_name[(?, ?, . . .)]}
Los corchetes indican que el material encerrado en ellos es opcional.
Estos no forman parte de la sintaxis.
Los argumentos de entrada pueden ser bien literales, bien parámetros.
Ver la sección 7 “CallableStatement” de esta guía.
Se puede llamar al método DatabaseMetaData.supportsStoredProcedures
para ver si la base de datos soporta procedimientos almacenados.
• oj para joins de salida
La sintaxis para un outer join es:
{oj outer-join}
donde outer-join es de la forma:
table LEFT OUTER JOIN {table | outer-join} ON search-condition
Las Outer joins son una característica avanzada, y solo puede chequearse la gramática SQL mediente una explicación de ella. JDBC provee tres métodos de DatabaseMetaData para determinar que tipos de outer joins soporta un driver: supportsOuterJoins, supportsFullOuterJoins, y supportsLimitedOuterJoins. El método Statement.setEscapeProcessing activa o desactiva el procesamiento de escape. Por defecto la característica se encuentra activada. Un programador debería desactivar esta característica en tiempo de ejecución cuando el rendimiento ha de ser máximo, pero normalmente debe estar activado. Debería notarse que setEscapeProcesing no trabaja con objetos PreparedStatement por que la sentencia ya está preparada para enviar a la base de datos antes de poder ser llamada.
Uso del método execute
El método execute debería usarse solamente cuando es posible que una
sentencia nos devuelva más de un objeto Resultset., mas de un update count o
una combinación de ambos. Estas múltiples posibilidades para resultados,
aunque raras, son posibles cuando se ejecutan ciertos procedimientos
almacenados o por la ejecución dinámica de una string SQL desconocida (esto
es, desconocida para el programador de la aplicación en tiempo de
compilación). Por ejemplo, una usuario podría ejecutar un procedimiento
almacenado (usando una objeto CallableStatement y este procedimiento podría
ejecutar una actualización, después una select, luego una actualización,
después una select y así. Normalmente, alguien que usa un procedimiento
almacenado sabrá que se le va a devolver.
Porque el método execute maneja los casos que se salen de lo
ordinario, no sorprende que los resultados devueltos requieren algun manejo
especial. Por ejemplo, supongamos que se sabe que el procedimiento devuelve
dos result sets.
Después de usar el método execute para ejecutar el procedimiento, se debe llamar al método getResultSet para conseguir el primer result set y después los métodos apropiados getXXX para recuperar los valores de él. Para conseguir el segundo result set, se necesita llamar al método getMoreResults y y despues a getResultSet de nuevo. Si se sabe que el procedimiento devuelve dos upadte counts, se llama primero al método getUpdateCount, seguido de getMoreResults y de nuevo getUpdateCount.
Aquellos casos en los que no se conoce que devolverá se nos presenta
una situación más compleja. El método execute devuelve true si el resultado
es un objeto ResultSet y false si es un int Java. Si devuelve un int, esto
quiere decir que el resultado o bien es un update count o que la sentencia
que ha ejecutado es un comando DDL. Lo primero que hay que hacer después de
llamar execute es llmar o bien a getResultSet o getUpdateCount. Al método
getResultSet se le llama para conseguir el primero de los dos o más objetos
ResultSet y al método getUpdateCount para conseguir el primero de dos o más
update counts.
Cuando el resultado de una sentencia SQL no es un result set, el
método getResultSet devolverá null. Esto quiere decir que el resultado es un
update count o que no hay más resultados. La única manera de encontrar que
significa el valor null en este caso es llamar al método getUpdateCount, que
devolverá un entero. Este entero será el número de filas afectadas por la
sentencia ejecutada o –1 para indicar o bien que el resultado es un result
set o bien que no hay más resultados. Si el método getResultSet ya ha
devuelto null, el resultado no puede ser un objeto ResultSet, por lo que el
valor devuelto de –1 tiene que ser que no hay más resultados. En otras palabras,
no hay más resultados cuando lo siguiente es cierto:
((stmt.getResultSet() == null) && (stmt.getUpdateCount() ==
-1))
Si se ha llamado al método getResultSet y se ha procesado el objeto
ResultSet devuelto, es necesario llamar al método getMoreResults para ver si
hay más result sets o update counts.. Si getMoreResults devuelve true,
entonces es necesario llamar de nuevo a getResultSet para recuperar el
siguiente result set. Como ya se ha indicado anteriormente, si getResultset
devuelve null hay que llamar a GetUpdateCount para buscar que significa ese
null si un update count o que no hay más resultados.
Cuando getMoreResults devuelve false quiere decir que la sentencia SQL
ha devuelto un update count o que no hay más resultados. Por tanto es
necesario llamar al método getUpdateCount para encontrar cual es el caso. En
esta situación, no habrá más resultados cuando lo siguiente es cierto:
((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
El siguiente código muestra una forma de asegurarse que se ha acce
dido a todos los result sets y update counts de una llamada al método execute:
stmt.execute(queryStringWithUnknownResults);
while (true) { int rowCount = stmt.getUpdateCount(); if (rowCount > 0) { // this is an update count System.out.println("Rows changed = " + count); stmt.getMoreResults(); continue; } if (rowCount == 0) { // DDL command or 0 updates System.out.println(" No rows changed or statement was DDL command"); stmt.getMoreResults(); continue; } // if we have gotten this far, we have either a result set // or no more results ResultSet rs = stmt.getResultSet; if (rs != null) { . . . // use metadata to get info about result set columns while (rs.next()) { . . . // process results stmt.getMoreResults(); continue; } break; // there are no more results |
Statement interface
The Statement interface provides
methods to execu
te queries with the database. The statement interface
is a factory of ResultSet i.e. it provides factory metho
d to get the object of ResultSet.
te queries with the database. The statement interface
is a factory of ResultSet i.e. it provides factory metho
d to get the object of ResultSet.
Commonly used methods of Statement
interface:
The important methods of Statement
interface are as follows:
1) public ResultSet executeQuery(String sql): is used to
execute SELECT query. It returns the object of ResultSet.
|
2) public int executeUpdate(String sql): is used to
execute specified query, it may be create, drop, insert, update, delete etc.
|
3) public boolean execute(String sql): is used to
execute queries that may return multiple results.
|
4) public int[] executeBatch(): is used to
execute batch of commands.
|
Example of Statement interface
Let’s see the simple example of
Statement interface to insert, update and delete the record.
1. import java.sql.*;
2. class FetchRecord{
3. public static void main(String args[])throws Exception{
4. Class.forName("oracle.jdbc.driver.OracleDriver");
5. Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","system","oracle");
6. Statement stmt=con.createStatement();
7. //stmt.executeUpdate("insert into emp765 values(33,'Irfan',50000)");
8. //int result=stmt.executeUpdate("update emp765 set name='Vimal',salary=10000 where id=33");
9. int result=stmt.executeUpdate("delete from emp765 where id=33");
10. System.out.println(result+" records affected");
11. con.close();
12. }}
Creada por el método
createStatement(). Un objeto Statement se usa para enviar sentencias SQL
simples.
1. Para ejecutar una
consulta (query), se llama al método:
executeQuery(sentenciaSQL) sobre un Statement.
2. Para ejecutar una
modificación, se llama al método:
executeUpdate(sentenciaSQL) sobre un Statement.
La interfaz Statement nos suministra
tres métodos diferentes para ejecutar sentencias SQL, executeQuery,
executeUpdate y execute. El método a usar está determinado por el producto de
la sentencia SQL
2. El método executeQuery está
diseñado para sentencias que producen como resultado un único ResultSet tal
como las sentencias SELECT.
3. El método executeUpdate se usa
para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL
(Data Definition Language) como CREATE TABLE o DROP TABLE.
El efecto de una sentencia INSERT,
UPDATE o DELETE es una modificación de una o más columnas en cero o más filas
de una tabla. El valor devuelto de executeUpdate es un entero que indica el
número de filas que han sido afectadas (referidos como update count).
Para sentencias tales como CREATE
TABLE o DROP TABLE, que no operan sobre filas, el valor devuelto por
executeUpdate es siempre cero.
4. El método execute se usa solamente
para ejecutar sentencias que devuelven más de un Result Set, más que un update
count o una combinación de ambos.
Ahora veamos un ejemplo con los
puntos anteriores:
//Creamos un objeto del tipo
Connection para realizar la conexión
Connection con =
DriverManager.getConnection(url, "usuario", "password");
//Creamos un objeto del tipo
Statement para poder enviar una sentencia SQL simple
Statement statement =
con.createStatement();
//Creamos un objeto "rs"
del tipo ResultSet para obtener los resultados, el cual enviará la sentencia
SQL "SELECT * from PRODUCTOS" la cual le dice a la base de datos que
estamos buscando todo el contenido (*) de la tabla PRODUCTOS.
ResultSet rs = statement.executeQuery
("SELECT * from PRODUCTOS");
Cerrar objetos Statement
Los objetos Statement se cerrarán
automáticamente por el colector de basura de Java (garbage collector). No
obstante se recomienda como una buena práctica de programación que se cierren
explícitamente cuando ya no sean necesarios.
Objetos Statement.
El objeto Statement (sentencia) sirve para procesar una sentencia SQL
estática y obtener los resultados producidos por ella. Solo puede haber un
ResultSet abierto para cadaobjeto Statement en un momento dado.
ü RESULSET: Un ResultSet
contiene todas las filas que satisfacen las condiciones de una sentencia SQL y
proporciona el acceso a los datos de estas filas mediante un conjunto de
métodos get que permiten el acceso a las diferentes columnas de la filas. El
método ResultSet.next se usa para moverse a la siguiente fila del result set,
convirtiendo a ésta en la fila actúal.
El formato general de un result set es una tabla con cabeceras de
columna y los valores correspondientes devueltos por
la ‘query’. Por ejemplo, si la ‘query’ es SELECT a, b, c FROM Table1, el
resultado tendrá una forma semejante a :
a b c
-------- --------- --------
12345 Cupertino CA
83472 Redmond WA
83492 Boston MA
El siguiente fragmento de código es un ejemplo de la ejecución de una
sentencia SQL que devolverá una colección de filas, con la columna 1 como un
int, la columna 2 como una String y la columna 3 como un array de bytes:
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1"); while (r.next()) { // print the values for the current row. int i = r.getInt("a"); String s = r.getString("b"); float f = r.getFloat("c"); System.out.println("ROW = " + i + " " + s + " " + f); }
FILAS Y CURSORES
Un ResultSet mantiene un cursor que apunta a la fila actúal de datos.
El cursor se mueve una fila hacia abajo cada vez que se llama al método next.
Incialmente se sitúa antes de la primera fila, por lo que hay que llamar al
método next para situarlo en la primera fila conviertiendola en la fila
actúal. Las filas de ResultSet se recuperan en secuencia desde la fila más
alta a la más baja.
Un cursor se mantiene válido hasta que el objeto Resultset o su objeto
padre Statement se cierra.
En SQL, el cursor resultado para una tabla tiene nombre. Si una base de datos permite upadtes posicionados o deletes posicionados, el nombre del cursor es necesario y debe ser proporcionado como un parámetro del comando update o delete. El nombre del cursor puede obtenerse mediante una llamada al método getCursorName.
No todas las bases de datos soportan updates o deletes posicionados.
Los métodos DatabaseMetaData.supportsPositionedDelete y
DatabaseMetaData.supportsPositionedUpdate nos permiten descubrir si estas
operaciones están soportadas en una conexión dada. Cuando lo están, el driver
o la DBMS deben asegurarse que las filas seleccionadas están apropiadamente bloquedas
y por tanto que estas operaciones no provoquen actualizaciones anomalas ni
otros problemas de concurrencia.
COLUMNAS
Los métodos getXXX suministran los medios para recuperar los valores
de las columnas de la fila actúal. Dentro de cada fila, los valores de las
columnas pueden recuperarse en cualquier orden, pero para asegurar la máxima
portabilidad, deberían extraerse las columnas de izquierda a derecha y leer
los valores de las columnas una única vez.
Puede usarse o bien el nombre de la columna o el número de columna
para referirse a esta. Por ejemplo: si la columna segunda de un objeto
RecordSet rs se denomina “title” y almacena valores de cadena, cualquiera de
los dos ejemplos siguientes nos devolverá el valor almacenado en la columna.
String s = rs.getString("title");
String s = rs.getString(2);
Nótese que las columnas se numeran de izquierda a derecha comenzando
con la columna 1. Además los nombres usados como input en los métodos getXXX
son insensibles a las mayúsculas.
La opción de usar el nombre de columna fue provista para que el
usuario que especifica nombres de columnas en una ‘query’ pueda usar esos
nombres como argumentos de los métodos getXXX. Si, por otro lado, la
sentencia select no especifica nombres de columnas (tal como en “select * from
table1” o en casos donde una columna es derivada), deben usarse los números
de columna. En estas situaciones , no hay forma de que el usuario sepa con
seguridad cuales son los nombres de las columnas.
En algunos casos, es posible para una query SQL devolver un result set
con más de una columna con el mismo nombre. Si se usa el nombre de columna
como argumento en un método getXXX, éste devolverá el valor de la primera
columna que coincida con el nombre. Por eso, si hay múltiples columnas con el
mismo nombre, se necesita usar un índice de columna para asegurarse que se
recupera el valor de la columna correcta. Esto puede ser ligeramente más
eficiente que usar los números de columna.
Información acerca de las columnas en un ResultSet es accesible
mediante el método ResultSet.getMetaData. El objeto ResultSetMetaData
devuelto nos da el número, tipo y propiedades de las columnas de los objetos
ResultSet.
Si se conoce el nombre de una columna, pero no su indice, puede usarse
el método findColumn para encontrar el número de columna.
|
Recuperar datos de ResultSet
El objeto ResultSet
proporciona varios métodos para obtener los datos de columna correspondientes a
una fila. Todos ellos tienen el formato get<Tipo>, siendo <Tipo>
un tipo de datos Java™. Algunos ejemplos de estos métodos son getInt, getLong,
getString, getTimestamp y getBlob. Casi todos estos métodos toman un solo
parámetro, que es el índice que la columna tiene dentro del ResultSet o bien el
nombre de la columna.
Las columnas de
ResultSet están numeradas, empezando por el 1. Si se emplea el nombre de la
columna y hay más de una columna que tenga ese mismo nombre en el ResultSet, se
devuelve la primera. Algunos de los métodos get<Tipo> tienen parámetros
adicionales, como el objeto opcional Calendar, que se puede pasar a los métodos
getTime, getDate y getTimestamp. Consulte el Javadoc del paquete java.sql para obtener todos los detalles.
En los métodos get
que devuelven objetos, el valor de retorno es null cuando la columna del
ResultSet es nula. En tipos primitivos, no puede devolverse null. En estos
casos, el valor es 0 o false. Si una aplicación debe distinguir entre null, y 0
o false, puede utilizarse el método wasNull inmediatamente después de la
llamada. A continuación, este método puede determinar si el valor era un valor
0 o false real o si ese valor se ha devuelto debido a que el valor de ResultSet
era de hecho null.
Soporte de ResultSetMetaData
Cuando se llama al
método getMetaData en un objeto ResultSet, el método devuelve un objeto
ResultSetMetaData que describe las columnas de ese objeto ResultSet. En los
casos en que la sentencia SQL que se va a procesar no se conoce hasta el
momento de la ejecución, puede utilizarse ResultSetMetaData para determinar
cuál de los métodos get hay que emplear para recuperar los datos. El ejemplo de
código siguiente utiliza ResultSetMetaData para determinar cada uno de los
tipos de columna del conjunto de resultados.
ResultSet rs = stmt.executeQuery(sqlString);
ResultSetMetaData rsmd = rs.getMetaData();
int colType [] = new int[rsmd.getColumnCount()];
for (int idx = 0, int col = 1; idx < colType.length; idx++, col++)
colType[idx] = rsmd.getColumnType(col);
EJEMPLOS:
EJEMPLO 01
MySQL con Java
Una vez instalado MySQL, descargado el driver para java de MySQL y con una base de datos y una tabla creada en MySQL, vamos a hacer un pequeño programa en java que nos permita conectarnos a la base de datos MySQL y consultar la tabla que hemos creado.
Instalar el Driver
En nuestro programa java, todos los import que necesitamos para manejar la base de datos están en java.sql.*. Puesto que casi todas los métodos relativos a base de datos pueden lanzar la excepción SQLException, meteremos todo nuestro programa en un try-catch.
Además, necesitamos la clase org.gjt.mm.mysql.Driver que viene con el driver de MySQL. Por ello, en nuestro CLASSPATH o incluido en nuestro proyecto con nuestro IDE favorito, debemos incluir el jar que contiene el driver MySQL (mysql-connector-java-3.1.7-bin.jar) o la versión más moderna y compatible con la versión de nuestro servidor de MySQL.
Lo primero que tenemos que hacer es asegurarnos que el Driver se inicializa y se registra, para ello
try
{
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e)
{
e.printStackTrace();
}
{
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e)
{
e.printStackTrace();
}
Establecer la conexión con la base de datos
Debemos tener el servidor de MySQL arrancado. Si hemos instalado y dejado esa opción como estaba, cada vez que encendamos el ordenador, se arrancará el servidor de MySQL, por lo que no tenemos que preocuparnos por ello.
El servidor de MySQL abre por defecto el puerto 3306 para aceptar conexiones de posibles clientes, de programas que quieran conectarse y acceder a la base de datos. Nuestro programa java, si quiere consultar la tabla de base de datos que hemos creado, deberá conectarse a este servidor.
Para establecer la conexion, la clase DriverManager tiene métodos getConnection(). Usaremos uno de ellos
// Establecemos la conexión con la base de datos.
Connection conexion = DriverManager.getConnection ("jdbc:mysql://localhost/prueba","root", "la_clave");
Connection conexion = DriverManager.getConnection ("jdbc:mysql://localhost/prueba","root", "la_clave");
El primer parámetro del método getConnection() es un String que contiene la url de la base de datos:
- jdb:mysql porque estamos utilizando un driver jdbc para MySQL, que es el que nos hemos bajado.
- localhost porque el servidor de base de datos, en mi caso, está en el mismo ordenador en el que voy a correr el prorama java. Aquí puede ponerse una IP o un nombre de máquina que esté en la red.
- prueba es el nombre de la base de datos que he creado dentro de mysql. Se debe poner la base de datos dentro del servidor de MySQL a la que se quiere uno conectar. Es el nombre que pusimos cuando desde SQL hicimos create database prueba;
Los otros dos parámetros son dos String. Corresponden al nombre de usuario y password para acceder a la base de datos. Al instalar MySQL se crea el usuario root y se pide la password para él. Como no hemos creado otros usuarios, usaremos este mismo.
Si todo va bien, en conexion tendremos nuestra conexión a la base de datos.
Esta conexión es en realidad un socket entre java y la base de datos, aunque para nosotros es transparente. Lo que sí es importante, es saber que si varios hilos comparten esta conexión, deben usarla sincronizadamente. Si no se hace así, los mensajes que van por el socket se pueden entremezclar y los hilos pueden leer cachos de mensaje destinados al otro hilo. Otra opción es que cada hilo cree su propia conexión. Finalmente, la mejor opción de todas si nuestra aplicación va a tener varios hilos intentando acceder a la base de datos, es usar un Pool de conexiones.
Realizar una consulta
Para realizar cualquier acción sobre la base de datos (consulta, insertar nuevos registros, modificar los existentes o borrar), necesitamos una clase Statement. Para obtenerla, se le pide dicha clase a la conexión. La forma de hacerlo, para una consulta, es la siguiente:
// Preparamos la consulta
Statement s = conexion.createStatement();
ResultSet rs = s.executeQuery ("select * from persona");
Statement s = conexion.createStatement();
ResultSet rs = s.executeQuery ("select * from persona");
La parte de createStatement() no tiene ningú secreto, salvo que puede lanzar una excepción que hay que capturar.
El Statement obtenido tiene un método executeQuery(). Este método sirve para realizar una consulta a base de datos.
- El parámetro que se pasa en un String en el que está la consulta en lenguaje SQL. No hace falta terminarlo con punto y coma. En nuestro caso "select * from persona". siendo persona el nombre que hemos puesto a la tabla en la base de datos.
- El resultado nos lo devuelve el método como un ResultSet. Este ResultSet no es más que una clase java similar a una lista en la que está el resultado de la consulta. Cada elemento de la lista es uno de los registros de la base de datos. En realidad, ResulSet no contiene todos los datos, sino que los va consiguiendo de la base de datos según se van pidiendo. Por ello, el método executeQuery() puede tardar poco, pero el recorrer los elementos del ResultSet no es tan rápido. De esta forma se evita que una consulta que dé muchos resultados tarde mucho tiempo y llene la memoria del programa java.
Leer los resultados
El ResultSet contiene dentro los registros leidos de la base de datos. Inicialmente, tal cual nos lo devuelve el Statement.executeQuery(), tiene internamente un "puntero" apuntando justo delante del primer registro. El método next() del ResultSet hace que dicho puntero avance al siguiente registro, en este caso, al primero. Si lo consigue, el método next() devuelve true. Si no lo consigue (no hay siguiente registro que leer), devuelve false.
Por tanto, una forma de ir leyendo los registros en meternos en un while.
// Recorremos el resultado, mientras haya registros para leer, y escribimos el resultado en pantalla.
while (rs.next())
{
System.out.println (rs.getInt (1) + " " + rs.getString (2)+ " " + rs.getDate(3));
}
while (rs.next())
{
System.out.println (rs.getInt (1) + " " + rs.getString (2)+ " " + rs.getDate(3));
}
Una vez que el "puntero" está apuntando a un registro, los métodos getInt(), getString(), getDate(), etc nos van devolviendo los valores de los campos de dicho registro. Podemos pasar a estos métodos un índice (que comienza en 1) para indicar qué columna de la tabla de base de datos deseamos. También podemos usar un String con el nombre de la columna (tal cual está en la tabla de base de datos).
Es responsabilidad nuestra saber qué tipo de dato hay en cada columna, aunque si nos equivocamos y RecordSet es capaz de hacer la conversión, la hará por nosotros. Por ejemplo, en cualquiera de los campos anteriores podemos pedir un getString() y nos devolveran los números como String y la fecha como String.
También podemos usar getObject(), y el RecordSet nos devolverá el Object más adecuado para el tipo de campo que pedimos.
Cerrar la conexión
Una vez que terminamos de usar la conexión, se debería cerrar, o bien terminar el programa, con lo que se cierra automáticamente.
// Cerramos la conexion a la base de datos.
conexion.close();
conexion.close();
EJEMPLO 03
2: RESUMEN
Java Database Connectivity, más conocida por sus siglas JDBC,es una API
que p
ermite la ejecución de operaciones sobre bases de datos desde el
lenguaje de pr
ogramación Java, independientemente del sistema operativo donde se
ejecute o
de la base de datos a la cual se accede, utilizando el dialecto SQL del
modelo de
base de datos que se utilice.
Para utilizar una base de datos particular, el usuario ejecuta su
programa junto c
on la biblioteca de conexión apropiada al modelo de su base de datos, y
accede
a ella estableciendo una
conexión; para ello provee el localizador a la base de
datos y los parámetros de conexión específicos.
Actualmente hay tres tipos de objetos Statement, todos los cuales actúan
como
contenedores para la ejecucion de
sentencias en una conexión dada: Stateme
nt, Prepared Statement que hereda de Statement y Callable Statement que
her
eda de Prepared Statement.Un objeto Prepared Statement se usa para
ejecuta
r sentencias SQL precompiladas con o sin parametros IN; y un objeto
Callable
Statement se usa para ejecutar un procedimieno de base de datos
almacenado.
Debe notarse que la interfase Prepared Statement, que hereda los metodos
de
la interfase Statement, tiene sus
propias versiones de los metodos execute Qu
ery, execute Update y execute.
3: SUMARY
Java Database
Connectivity, better known by its acronym JDBC is an API that allows the
execution of operations on databases from the Java programming language,
regardless of operating system you are running or the database which is
accessed, using the SQL dialect of the database model used.
To use a
particular database, the user runs the program along with the appropriate
connection library to model your database and accessed by establishing a
connection; for it provides the locator to the database and specific connection
parameters.
There are
currently three types of Statement objects, all of which act as containers for
the execution of sentences in a given connection: Statement, Statement Prepared
inherits from Statement and Callable Statement that inherits from Prepared
Statement.
Prepared Statement
object is used to execute precompiled SQL statements with or without IN
parameters; and Callable Statement object is used to execute a stored
procedimieno data base.
It should be
noted that the interface Prepared Statement, which inherits the methods of the
Statement interface has its own versions of Query methods execute, execute and
execute Update
4: RECOMENDACIONES
§ Evitar
el uso de System.out.println(), este es un recurso serializado y requiere el
uso de I/O en cada llamado.
§ En
EJBs marcar como transaccionales únicamente los métodos necesarios.
§ Usar
al máximo sentencias de base de datos precompiladas a través de la clase PreparedStatement cuando
ejecute sentencias SQL. Esto evita que la base de datos compile varias veces la
misma consulta y agiliza le ejecución de la sentencia.
§ Paginar
los resultados extensos (más de 100 registros) de bases de datos.
§ Evite
el uso de colecciones sincronizadas como Hashtable o Vector,
estas implementaciones tienen todos sus métodos sincronizados lo que implica
que generan bloqueos incluso para las operaciones de lectura. En vez de ello
utilice implementaciones más sofisticadas como ConcurrentHashMap o CopyOnWriteArrayList que
sólo bloquean las operaciones que modifiquen el contenido del objeto.
§ Las
conexiones hacia base de datos son recursos finitos y costosos en términos de
tiempos de respuesta; para causar el menor impacto en la aplicación haga caso
de las siguientes recomendaciones:
· Siempre que abra
una conexión, hágalo en el momento exacto de su uso y ciérrela de forma
incondicional.
5: CONCLUCIONES
a) Aprender a utilizar las clases e
interfaces disponibles en el API JDBC para
comunicarse con un gestor de base de
datos desde aplicaciones en Java.
b) Utilizar el API JDBC para obtener
información de los datos de una base de datos (Metadata).
6: APRECIACION DEL EQUIPO
a) Para Nosotras se ha hecho mas complicado la conexion con base de datos y java debido a que necesita muchas configuraciones.
b) Por otra mas nos parece mas seguro,y mejor trabajable.
7: GLOSARIO DE TERMINOS
ation Programming
Interface), es el conjunto de subrutinas, funciones y procedimientos (o
métodos, en la programación orientada a
objetos) que ofrece cierta biblioteca para ser ut
ilizado por otro
software como una capa de abstracción.
CICS: Es un sistema diseñado para procesar
tanto transacciones online como batch. En
los grandes
ordenadores IBM zSeries, un sistema CICS puede dar servicio a miles de tr
ansacciones por
segundo. Es una pieza clave en los servicios de muchos bancos, admin
istraciones y
grandes empresas. Las aplicaciones CICS pueden ser escritas en diferente
s lenguajes
HTTP: Hypertext Transfer Protocol o HTTP (en español protocolo de transferen
cia de hipertexto) es el protocolo de comunicación que permite las
transferenci
as de información en la World Wide Web.
ROLLBACKTRANS: Deshace todos los cambios efectuados en la base de d
atos desde el inicio de la transacción.
COMMITTRANS: Cierra una transacción haciendo efectivos los cambios efe
ctuados dentro de ella.
QUERY: consulta
realizada contra una base de datos. Se usa para
obtener datos, modificarlos o bien borrarlos.
8: BIBLIOGRAFIA O LINKOGRAFIA