Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Instalacion y Configuracion de JDBC
Instalacion y Configuracion de JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Indice
1. Introducci
on
1.1. JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2. Realizaci
on de la conexi
on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3. Obtenci
on de metadatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4. Ejecuci
on de sentencias SQL
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5. Obtenci
on de los resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.
Introducci
on
Se obtiene el archivo
mysql-connector-java-3.0.14-production.zip
Pagina: 1
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Este fichero debe estar en un sitio visible para Java tanto al compilar la aplicacion como al ejecutarla.
j a v a c c l a s s p a t h mysqlc o n n e c t o r ja va 3.0.12 p r o d u c t i o n . j a r ; . A p l i c a c i o n . j a v a
j a v a c l a s s p a t h mysqlc o n n e c t o r ja va 3.0.12 p r o d u c t i o n . j a r ; . A p l i c a c i o n
1.1.
JDBC
JDBC: Java DataBase Connectivity (Conexion con Bases de Datos mediante Java).
Que es JDBC? es una biblioteca de clases que permite la conexion con Bases de Datos que soporten
SQL utilizando Java.
Permite realizar operaciones (consultas, actualizaciones, ...) sobre bases de datos relacionales utilizando SQL (Structured Query Language).
Que ventajas ofrece acceder a la base de datos utilizando JDBC y Java? Que la aplicacion ser
a independiente de la plataforma y que se puede mover la aplicacion de un sistema gestor de bases de
datos a otro (por ejemplo de Oracle a MySQL o a Microsoft SQL Server o a...).
Los controladores JDBC se pueden clasificar como:
Controladores tipo 1: traducen JDBC a ODBC y se delega en ODBC para la comunicacion con la base de datos. Sun incluye uno de estos controladores con el J2SE.
Controlador tipo 2: esta escrito parcialmente en Java y en codigo nativo.
Controlador tipo 3: es una biblioteca cliente escrita completamente en Java que utiliza
un protocolo independiente de la BD para comunicar las peticiones a un servidor que
las traduce a un protocolo especfico de la Base de Datos.
Controlador tipo 4: es una biblioteca escrita completamente en Java que traduce las
peticiones a un protocolo especfico de la Base de Datos.
Resumiendo:
Pagina: 2
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Mediante JDBC se pueden escribir aplicaciones Java en las que se puede acceder a
Bases de Datos utilizando sentencias SQL estandar.
Las clases proporcionadas en los paquetes java.sql y javax.sql definen el API JDBC.
Sun ofrece u
nicamente un controlador del tipo 1 (puente JDBC/ODBC).
Los distribuidores de Bases de Datos pueden ofrecer los controladores optimizandolos
para sus productos.
1.2.
Cliente JDBC
Servidor
de la BD
Protocolo de la BD
La desventaja que tiene esta arquitectura es que la Base de Datos es directamente accesible y es
complicado el control sobre el tipo de consultas que se pueden realizar.
Pagina: 3
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Cliente
(Presentacion)
Capa intermedia
(L
ogica empresarial) JDBC
Servidor
de la BD
Protocolo de la BD
La ventaja es que la Base de Datos queda oculta tras la capa intermedia. Es mucho mas f
acil
controlar el tipo de consultas (ya que estas se realizan desde la capa intermedia sobre la que se
tiene pleno control).
2.
Los pasos a realizar para utilizar JDBC en una aplicacion Java son los siguientes:
2.1.
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Lo primero que hemos de hacer es ver cual es la clase que implementa a esta interfaz en el controlador JDBC que vamos a utilizar:
Por
ejemplo,
en
el
controlador
proporcionado
por
MySQL
la
clase
es
com.mysql.jdbc.Driver
Una vez identificado el controlador debe ser registrado para poder ser utilizado en la aplicaci
on.
Existen dos posibilidades:
Como un argumento pasado a la maquina virtual desde la lnea de ordenes
j a v a Djdbc . d r i v e r s=com . mysql . j d b c . D r i v e r A p l i c a c i o n
Por supuesto, al inicio de nuestra aplicacion debe aparecer (al menos) la siguiente biblioteca de
clases:
import java . s q l . ;
Ejemplos:
j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / L i b r o s ? u s e r=u s u a r i o&password=c l a v e
Se especifica que la base de datos esta en la maquina local, que el puerto donde escucha mysql es
el 3306, que la base de datos a utilizar es Libros, que el usuario es usuario y que el password es clave
Pagina: 5
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
j d b c : mysql : / / e p i . uv . e s : 3 3 0 6 / V i a j e s ? u s e r=admin&password=admin48
Se especifica que la base de datos esta en la maquina cuyo nombre es epi.uv.es, que el puerto donde
escucha mysql en esa maquina es el 3306, que la base de datos a utilizar es Viajes, que el usuario es
admin y que el password es admin48
2.2.
Realizaci
on de la conexi
on
Una vez que se ha registrado la clase del controlador se puede una instancia de Connection.
Para ello se utiliza el metodo estatico getConnection() de la clase DriverManager.1
p u b l i c s t a t i c C o n n e c t i o n g e t C o n n e c t i o n ( S t r i n g u r l ) t h r o w s SQLException
Cuando se llama a este metodo, el DriverManager intentara localizar un controlador apropiado entre
los que se hayan registrado.
La siguiente porcion de codigo muestra como se puede realizar esto:
...
try {
C l a s s . forName ( com . mysql . j d b c . D r i v e r ) ;
S t r i n g u r l = j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / e s t a n c i a s ? u s e r=u s u a r i o&password=c l a v e ;
C o n n e c t i o n conn = DriverManager . g e t C o n n e c t i o n ( u r l ) ;
// R e a l i z a r a l g o con l a c o n e x i o n
...
} c a t c h ( SQLException ex ) {
// h a n d l e any e r r o r s
System . out . p r i n t l n ( SQLException : + ex . g e t M e s s a g e ( ) ) ;
System . out . p r i n t l n ( SQLState : + ex . getSQLState ( ) ) ;
System . out . p r i n t l n ( VendorError : + ex . g e t E r r o r C o d e ( ) ) ;
}
...
2.3.
Obtenci
on de metadatos
Mediante la interfaz DatabaseMetaData es posible obtener informacion del sistema gestor de bases
de datos o de una determinada base de datos.
1
La interfaz DataSource, nueva en JDBC 2.0, proporciona otra forma de conectarse con una fuente de datos. El uso
de un objeto DataSource es el metodo recomendado para conectarse a una fuente de datos desde una aplicaci
on web.
Pagina: 6
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Utilizando esta clase se podran obtener las capacidades de un determinado sistema gestor de bases
de datos.
Esta clase dispone de entre otros (cons
ultese el API para un listado completo) los siguientes
metodos:
p u b l i c S t r i n g getDatabaseProductName ( )
Nombre d e l SGBD
p u b l i c String getDatabaseProductVersion ( )
Versi
o n d e l SGBD
p u b l i c S t r i n g getDriverName ( )
Nombre d e l c o n t r o l a d o r
public String getDriverVersion ()
Versi
on del controlador
p u b l i c R e s u l t S e t g e t C a t a l o g s ( ) t h r o w s SQLException
L i s t a d o de l a s b a s e s de d a t o s e x i s t e n t e s
p u b l i c R e s u l t S e t g e t T a b l e s ( S t r i n g c a t a l o g , S t r i n g schemaPattern , S t r i n g tableNamePattern ,
String [ ] types )
L i s t a d o de l a s t a b l a s en una b a s e de d a t o s
Ejemplo : r e f e r e n c i a . g e t T a b l e s ( e s t a n c i a s , % , % , n u l l ) ; }
p u b l i c R e s u l t S e t ge tT a bl eT yp e s ( ) t h r o w s SQLException
L i s t a d o con l o s t i p o s de t a b l a s s o p o r t a d a s por e l SGBD
Pagina: 7
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Ejercicio 1
Realizar una conexion con la base de datos de otra maquina y mostrar la siguiente informacion:
El nombre del SGBD
La version
El nombre del controlador
La version del controlador
2.4.
Ejecuci
on de sentencias SQL
La ejecucion de sentencias en la base de datos a traves de JDBC se realiza mediante las interfaces
Statement o PreparedStatement.
Los objetos de estos tipos se obtienen a partir del objeto de tipo Connection
2.4.1.
La interfaz Statement
Mediante objetos de este tipo se pueden ejecutar sentencias SQL sencillas y obtener los resultados
mediante la clase ResulSet.
Para obtener un objeto del tipo Statement se llama al metodo createStatement() del objeto Connection.
Una vez que se dispone del objeto se pueden ejecutar sentencias SELECT (que no modifican las
tablas) utilizando el metodo
R e s u l S e t e x e c u t e Q u e r y ( S t r i n g SQL)
El resultado de la consulta se devuelve en un objeto del tipo ResultSet, es decir, para acceder a la
informacion habra que utilizar los metodos de esta clase.
Para ejecutar sentencias que contengan UPDATE, INSERT o DELETE hay que utilizar el metodo
i n t e x e c u t e U p d a t e ( S t r i n g SQL)
Nota: he renombrado el fichero jar con el controlador para que tenga un nombre m
as corto.
Pagina: 8
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Este metodo devuelve true si la sentencia contena un SELECT y false en caso contrario.
Si la sentencia contena un SELECT se pueden obtener los resultados llamando al metodo getResultSet() que devuelve un objeto del tipo ResulSet.
En caso contrario se puede obtener el n
umero de filas afectadas llamando al metodo getUpdateCount().
Ejemplos:
...
Statement s = DriverManager . g e t C o n n e c t i o n ( u r l ) . c r e a t e S t a t e m e n t ( ) ;
ResulSet rs ;
S t r i n g s e n t e n c i a S Q L = SELECT FROM c a s a s ;
r s = s . executeQuery ( sentenciaSQL ) ;
...
...
Statement s = DriverManager . g e t C o n n e c t i o n ( u r l ) . c r e a t e S t a t e m e n t ( ) ;
i n t filasMod ;
S t r i n g s e n t e n c i a S Q L = update c a s a s s e t DispHasta = 2004 11 30 where IdCasa=7 ;
filasMod = s . executeUpdate ( sentenciaSQL ) ;
...
...
Statement s = DriverManager . g e t C o n n e c t i o n ( u r l ) . c r e a t e S t a t e m e n t ( ) ;
boolean tipoSentencia ;
B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r ( new InputStreamReader ( System . i n ) ) ;
s e n t e n c i a S Q L = br . r e a d L i n e ( ) ;
t i p o S e n t e n c i a = s . execute ( sentenciaSQL ) ;
i f ( tipoSentencia ){
ResulSet rs = s . getResultSet () ;
...
} else
i n t f i l a s M o d = s . getUpdateCount ( ) ;
...
}
...
2.4.2.
La interfaz PreparedStatement
La interfaz PreparedStatement extiende a la interfaz Statement y utiliza una plantilla para crear la
sentencia SQL.
Se utiliza en aquellas situaciones en las que se necesita ejecutar varias veces una consulta en la
que pueden cambiar u
nicamente los parametros. De esta forma (si el SGBD lo permite) se optimiza
la consulta una sola vez.
Pagina: 9
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Par obtener un objeto del tipo PreparedStatement se llamara al metodo prepareStatement(.) del objeto
del tipo Connection.
A este metodo hay que pasarle la plantilla donde se especifican los lugares donde iran los par
ametros.
Los parametros son despues especificados utilizando los metodos setXXX(.) indicando el n
umero de
parametro y el dato a insertar en la sentencia.
La sentencia se ejecuta cuando se llama a los metodos executeQuery() o executeUpdate()
PreparedStatement de consulta
Por ejemplo supongamos que hay un campo de texto en el que el usuario puede introducir su
direccion de correo electronico y con este dato se desea buscar al usuario:
...
C o n n e c t i o n con = DriverManager . g e t C o n n e c t i o n ( u r l ) ;
S t r i n g c o n s u l t a = SELECT u s u a r i o FROM r e g i s t r o WHERE e m a i l l i k e ? ) ;
P r e p a r e d S t a t e m e n t pstmt = con . p r e p a r e S t a t e m e n t ( c o n s u l t a ) ;
pstmt . s e t S t r i n g ( 1 , campoTexto . g e t T e x t ( ) ) ;
R e s u l t S e t r e s u l t a d o = ps . e x e c u t e Q u e r y ( ) ;
...
PreparedStatement de modificaci
on
2.5.
Obtenci
on de los resultados
Como hemos visto en los ejemplos anteriores el resultado de una consulta es devuelto en un objeto
del tipo ResultSet.
Pagina: 10
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Podemos imaginar que el resultado se devuelve en forma de tabla donde las filas corresponden a
los registros y las columnas a los datos.
Primero hay que colocarse en una determinada fila y a continuacion acceder a la columna deseada.
Para ello, la clase ResultSet dispone de metodos para moverse en filas y de metodos para seleccionar
una determinada columna.
Algunos de los metodos disponibles para recorrer los registros son3 :
void beforeFirst ()
Posici
on por defecto, coloca el cursor antes del primer resultado.
void f i r s t ()
void afterLast ()
void l a s t ()
Coloca el cursor en la u
ltima fila del resultado.
boolean next ( )
boolean previous ()
3
Por defecto los objetos del tipo ResultSet no son actualizables y tienen un cursor que s
olo puede ir hacia adelante.
Por tanto, se puede iterar a lo largo de el una sola vez y desde el inicio hasta el final. Es posible crear ResultSet que se
puedan actualizar y/o que permitan libertad de movimientos. Se ver
a m
as adelante
Pagina: 11
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Para seleccionar columnas una vez que nos hemos colocado en un determinado registro se dispone
de dos conjuntos de metodos.
Por un lado metodos que reciben un entero (que indica el n
umero de la columna) y por otro
metodos que reciben el nombre de la columna.
Por ejemplo si se desea obtener el valor de una columna que es de tipo float se dispone de los dos
metodos:
f l o a t g e t F l o a t ( i n t numeroColumna )
f l o a t g e t F l o a t ( S t r i n g nombreColumna )
Se pueden obtener metadatos relacionados con el ResultSet utilizando el metodo getMetaData() que
devuelve un objeto del tipo ResultSetMetaData
Algunos de los metodos disponibles en esta clase son:
i n t getColumnCount ( )
Devuelve el n
umero de columnas que hay en el ResultSet.
S t r i n g getColumnName ( i n t column )
S t r i n g getColumnTypeName ( i n t column )
Ejemplo:
import java . s q l . ;
p u b l i c c l a s s EjemploResultSet {
Pagina: 12
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
try {
S t r i n g u r l = j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / e s t a n c i a s ? u s e r=u s u a r i o&password=c l a v e ;
C l a s s . forName ( com . mysql . j d b c . D r i v e r ) ;
C o n n e c t i o n con = DriverManager . g e t C o n n e c t i o n ( u r l ) ;
Statement s = con . c r e a t e S t a t e m e n t ( ) ;
ResultSet resultado ;
S t r i n g s e n t e n c i a S Q L = SELECT Ciudad , DispDesde , DispHasta
r e s u l t a d o = s . executeQuery ( sentenciaSQL ) ;
FROM c a s a s ;
println () ;
p r i n t l n ( Numero de columnas : + rsmd . getColumnCount ( ) ) ;
p r i n t l n ( Nombre de l a p r i m e r a columna : + rsmd . getColumnName ( 1 ) ) ;
p r i n t l n ( Tipo de l a p r i m e r a columna : + rsmd . getColumnTypeName ( 1 ) ) ;
println () ;
resultado . beforeFirst () ;
w h i l e ( r e s u l t a d o . next ( ) ) {
S t r i n g c i u = r e s u l t a d o . g e t S t r i n g ( Ciudad ) ;
j a v a . s q l . Date f e c h 1 = r e s u l t a d o . g e t D a t e ( DispDesde ) ;
j a v a . s q l . Date f e c h 2 = r e s u l t a d o . g e t D a t e ( DispHasta ) ;
System . out . p r i n t ( Casa en : + c i u ) ;
System . out . p r i n t (
Desde : + f e c h 1 ) ;
System . out . p r i n t (
Hasta : + f e c h 2 ) ;
System . out . p r i n t l n ( ) ;
}
con . c l o s e ( ) ;
} c a t c h ( SQLException ex ) {
System . out . p r i n t l n ( SQLException : + ex . g e t M e s s a g e ( ) ) ;
System . out . p r i n t l n ( SQLState : + ex . getSQLState ( ) ) ;
System . out . p r i n t l n ( VendorError : + ex . g e t E r r o r C o d e ( ) ) ;
} c a t c h ( ClassNotFoundException e ) {
System . out . p r i n t l n ( No s e e n c u e n t r a e l c o n t r o l a d o r ) ;
}
}
}
INTEGER o INT
SMALLINT
NUMERIC(m,n), DECIMAL(m,n) o DEC(m,n)
FLOAT(n)
REAL
DOUBLE
CHARACTER(n) o CHAR(n)
VARCHAR(n)
BOOLEAN
DATE
TIME
TIMESTAMP
BLOB
ARRAY
int
short
java.sql.Numeric
double
float
double
String
String
boolean
java.sql.Date
java.sql.Time
java.sql.Timestamp
java.sql.Blob
java.sql.Array
Ojo, puede que alguno de los tipos de la izquierda no esten soportados por todas las Bases de
Pagina: 13
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Ejercicio 3
Debido a la devaluacion de la libra esterlina respecto al euro se desea incrementar en un 5 por
ciento el precio por da de todas las casas del Reino Unido. Realizar la actualizacion de los
precios.
Las versiones anteriores a JDBC 2.0 devolvan los resultados con cursores que solo podan ir hacia
adelante. Cada elemento se obtena llamando al metodo next().
A partir de JDBC 2.0 se puede recorrer el resultado en las dos direcciones y se puede actualizar el
resultado si esta operaci
on est
a soportada por la base de datos.
Una ventaja es que se pueden actualizar una serie de columnas sin necesidad de enviar ninguna
llamada executeUpdate(). La actualizacion se realiza de forma automatica.
A la hora de obtener tanto un Statement como un PreparedStatement es posible especificar (si la
base de datos lo acepta) el tipo de desplazamiento deseado y si se desea que las modificaciones en el
resultado se reflejen en la base de datos.
// Supongo que conn e s d e l t i p o Connexion
// Para c r e a r un S t a t e m e n t
Statement stmt = conn . c r e a t e S t a t e m e n t ( i n t t i p o R e s u l t a d o , i n t t i p o A c t u a l i z a c i o n ) ;
// Para c r e a r un P r e p a r e d S t a t e m e n t
P r e p a r e d S t a t e m e n t pstmt = conn . p r e p a r e S t a t e m e n t ( S t r i n g s q l , i n t t i p o R e s u l t a d o , i n t
tipoActualizacion ) ;
Pagina: 14
JDBC
Julio 2004.
MySQL y Java
Universitat de Val`encia
Es posible verificar si la Base de Datos soporta estos tipos utilizando el siguiente metodo
// Supongo que conn e s d e l t i p o Connexion
i n t tipoResultado = ResultSet . . . . ;
i n t tipoActualizacion = ResultSet . . . . ;
b o o l e a n e s P o s i b l e = conn . getMetaData ( ) . s u p p o r t s R e s u l t S e t C o n c u r r e n c y ( t i p o R e s u l t a d o ,
tipoActualizacion ) ;
En cuanto a la actualizacion del resultado se pueden utilizar los metodos updateTIPO(.) (donde
TIPO es el tipo de dato a actualizar) que ofrece la interfaz ResultSet.
A continuacion se enva el mensaje updateRow() al objeto del tipo ResultSet para que actualice la
fila en la base de datos.
Por ejemplo, el siguiente codigo se puede utilizar para modificar el valor de la fecha en el resultado
y actualizar la base de datos:
// Asumo que r s e s una r e f e r e n c i a d e l t i p o R e s u l t S e t
r s . a b s o l u t e ( 5 ) ; // mueve e l c u r s o r a l a
fila 5
// a c t u a l i z a l a f e c h a en e l R e s u l t S e t
r s . updateDate ( Fecha , 20040401 ) ;
// A c t u a l i z a l a f e c h a en l a b a s e de d a t o s para e l
// r e g i s t r o s e l e c c i o n a d o
r s . updateRow ( ) ;
Ejercicio 4
Realizar la actualizacion de los precios del ejercicio 3 del siguiente modo:
Crear un Statement en el que se permita el movimiento en cualquier direccion y en el que las
actualizaciones se reflejan en cuanto se producen y ademas que el resultado sea actualizable.
Ejecutar una sentencia de consulta en la que se seleccione el pais y el precio de todas las casas.
Recorrer el ResultSet obtenido mostrando el pais y el precio y si ademas el pais es el Reino Unido
actualizar el precio por da subiendolo un 5 por ciento.
Pagina: 15