Conexión a Bases de Datos: JDBC, DAO

Anuncio
26/04/2007
Bases de Datos en Java:
JDBC y Patrón DAO
26/04/2007
DAI
Contenido
z
z
z
z
z
z
z
z
2
Definición.
Arquitectura.
Driver.
Conexión.
Consultas.
Transacciones
Transacciones.
Pool de conexiones.
Patrón DAO.
Curso 2006/2007
1
26/04/2007
JDBC
z
z
z
z
z
Java DataBase Connectivity
API Java para ejecutar consultas SQL en Bases de
Datos Relacionales.
Independiente del Sistema Gestor Relacional.
– Similar en concepto a ODBC de Windows.
Distribuida en dos paquetes:
– java.sql, dentro de J2SE
– javax.sql extensión dentro de J2EE
Para acceder a una base de datos es necesario un
driver.
– Implementación de todas las interfaces del API.
3
Curso 2006/2007
JDBC
z
El API ofrece las clases e interfaces para:
– Establecer una conexión a una base de datos.
– Ejecutar una consulta.
– Procesar los resultados.
// Establece la conexión
Connection con = DriverManager.getConnection (
"jdbc:odbc:miBD", ”miLogin", ”miPassword");
// Ejecuta la consulta
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT nombre, edad FROM Empleados");
// Procesa los resultados
while (rs.next()) {
String nombre = rs.getString(”nombre");
int edad = rs.getInt(”edad");
}
4
Curso 2006/2007
2
26/04/2007
Arquitectura
ResultSet
Statement Statement
Statement
Connection
Connection
Aplicación
DriverManager
Driver
Driver
JVM
5
Access
Curso 2006/2007
Oracle
Driver
z
z
6
Conjunto de clases encargadas de implementar las interfaces del API y
acceder a la base de datos.
Tipos:
– Driver Tipo 1:
z Utilizan un API nativa estándar
z Ejemplo: puente JDBC:ODBC
– Driver Tipo 2:
z Utilizan un API nativa de la base de datos
z Ejemplo: Oracle OCI
– Driver
Di
Ti
Tipo 3:
3
z Servidor remoto con un API genérica.
z Útil para aplicaciones en internet.
– Driver Tipo 4:
z Totalmente desarrollado en Java
z Ejemplo: Oracle Thin.
Curso 2006/2007
3
26/04/2007
Driver
z
z
Los drivers Tipo 1 y 2 utilizan código nativo vía JNI.
– Son más eficientes.
Diseño Driver Tipo 3:
En aplicaciones enterprise favorecen la gestión de las bases de datos,
que se realiza en el servidor.
Carga de un driver: Class.forName(“acme.db.Driver”);
Repositorio de drivers:
– http://industry.java.sun.com/products/jdbc/drivers
–
z
z
7
Curso 2006/2007
Conexión
z
z
z
z
8
Representa una conexión con una base de datos.
Se obtienen a partir de la clase DriverManager:
– DriverManager.getConnection(“URL”, “login”, “password”)
– Mantiene un registro de todos los drivers cargados en la
JVM.
URL identifica el driver y su tipo, la localización de la base de
d t y su nombre:
datos
b
– jdbc:oracle:oci:dis.um.es/MiBD
Alternativa a DriverManager: DataSource
Curso 2006/2007
4
26/04/2007
DataSource
z
z
z
z
9
Actúa como factoría de conexiones.
– Método getConnection()
Abstrae los detalles de acceso:
– Cargar los drivers, URL, login, etc.
– Aplicaciones más portables.
Suelen mantener un pool de conexiones.
Proporcionado por el contenedor utilizando el API JNDI (Java
Naming and Directory Interface).
– Los detalles de acceso se indican en ficheros de configuración.
– Acceso a los servicios de nombres y directorios.
– Ejemplo: acceso a recursos, LDAP.
Curso 2006/2007
Consultas SQL
z
z
z
z
10
El API JDBC no restringe las sentencias que se envían a la BD.
En principio, todos los drivers deben ser compatibles con ANSI SQL-2
Entry Level.
Tipos de sentencias:
– Statement: para sentencias sencillas en SQL.
– PreparedStatement: para consultas preparadas,
z Ejemplo: las que tienen parámetros.
– CallableStatement: para ejecutar procedimientos almacenados en
la BD.
El API distingue dos tipos de consultas:
– Consultas: SELECT
– Actualizaciones: INSERT, UPDATE, DELETE, sentencias DDL.
Curso 2006/2007
5
26/04/2007
Statement
z
z
z
Son creadas a partir de la conexión:
– Statement stmt = conexion.createStatement();
Ejecución de una consulta:
– stmt.executeQuery(“SELECT * FROM Pedidos”);
– Devuelve un objeto ResultSet.
Ejecución de una actualización:
– stmt.executeUpdate(“DELETE FROM Pedidos WHERE
codigo = 15”)
– Devuelven un entero indicando los registros actualizados ó
0 si es una consulta DDL.
11
Curso 2006/2007
ResultSet
z
z
z
12
Es un proxy sobre los registros del resultado de la búsqueda.
– Controla la recuperación de los registros.
Representa un cursor (iterador) sobre los resultados.
– Movimiento: métodos next() y previous()
– Inicialmente el cursor está posicionado antes del primer
registro.
Depende del objeto consulta:
– Cada vez que se realice una consulta se pierden los
resultados.
Curso 2006/2007
6
26/04/2007
ResultSet
z
z
z
13
Tenemos dos alternativas para acceder a las columnas del
resultado:
– rs.getString(“nombre”); ⇒ Nombre de la columna
– rs.getString(1); ⇒ Posición en la consulta
El acceso por posición es útil cuando:
– Acceso a una columna derivada, ej. calcular la media
– Cuando hay columnas con los mismos nombres (join)
Recuperación de los valores de las columnas:
– Métodos de acceso (getXXX).
– Es conveniente leer los datos de izquierda a derecha.
– Para averiguar si se ha leído un nulo: wasNull()
Curso 2006/2007
ResultSet – Métodos de Acceso
Tipo de dato SQL
CHAR
VARCHAR
LONGVARCHAR
NUMERIC
DECIMAL
BIT
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT
DOUBLE
BINARY
VARBINARY
DATE
TIME
TIMESTAMP
14
Método de Acceso
String getString()
String getString()
InputStream
getAsciiStream() ó
getUnicodeString()
java.math.BigDecimal
getBigDecimal()
java.math.BigDecimal
getBigDecimal()
boolean getBoolean()
byte getByte()
short getShort()
int getInt()
l
long
getLong()
tL
()
float getFloat()
double getDouble()
double getDouble()
byte[] getBytes()
InputStream
getBinayStream()
java.sql.Date getDate()
java.sql.Time getTime()
java.sql.TimeStamp
getTimeStamp()
Curso 2006/2007
7
26/04/2007
PreparedStatement
z
z
15
Problema con Statement:
– Cuando la consulta se realiza dentro de un bucle y varía
sólo en unos valores:
z stmt.executeQuery(“SELECT * FROM Cliente WHERE
codigo = “ + i);
z La base de datos planifica cada consulta.
– Î Conviene disponer de una consulta con parámetros.
PreparedStatement:
– Especialización de Statement que permite definir consultas
parametrizadas.
– La BD sólo planifica la consulta cuando se crea.
– Evitan tener que formatear los datos al construir la cadena
de consulta: ‘ ’ para cadenas, fechas y horas.
Curso 2006/2007
PreparedStatement
z
z
z
16
También se crean a partir de la conexión:
– PreparedStatement pstmt =
conexion.prepareStatement(“SELECT * FROM Cliente WHERE
codigo = ?”)
Los parámetros de entrada se especifican por posición utilizando
métodos setXXX:
– psmt.setInt(1, 20);
– Misma equivalencia que los getXXX de ResultSet.
– Los valores se conservan entre ejecuciones.
z Borrar parámetros: clearParameters()
Ejecución:
– Consulta: executeQuery().
– Actualización: executeUpdate().
Curso 2006/2007
8
26/04/2007
Transacciones
z
z
z
17
Ejecución de bloques de consultas SQL manteniendo las
propiedades ACID (Atomicy-Consistency-Isolation-Durability)
Una conexión funciona por defecto en modo autocommit:
– Cada consulta representa una sola transacción.
– Método: conexion.setAutocommit(false);
Definimos bloques de consultas:
– Deshabilitando el modo autocommit.
– Finalizamos la transacción ejecutando commit() o
rollback() sobre la conexión.
Curso 2006/2007
Nivel de Aislamiento
Transaccional
z
z
18
Niveles de aislamiento:
– TRANSACTION_NONE:
z Sin soporte transaccional.
– TRANSACTION_READ_UNCOMMITED:
z Permite lecturas sobre datos no comprometidos.
– TRANSACTION_READ_COMMITED:
z Permite lecturas sólo sobre datos comprometidos.
z Nivel por defecto.
– TRANSACTION_REPEATABLE_READ.
z Bloquea los datos leídos.
– TRANSACTION_SERIALIZABLE.
z Sólo una transacción al mismo tiempo.
Suelen estar disponibles read commited y serializable.
Curso 2006/2007
9
26/04/2007
Concurrencia
z
z
19
Establecer el modo de aislamiento:
– conexion.setTransactionIsolation(
Connection.TRANSACTION_SERIALIZABLE);
Consejos de uso:
– Bloque con sólo actualizaciones:
z TRANSACTION_READ_COMMITED
– Bloque donde leamos varias veces el mismo registro:
z TRANSACTION_REPEATABLE_READ
TRANSACTION REPEATABLE READ
– Bloque en el que leamos un valor para actualizarlo:
z TRANSACTION_SERIALIZABLE
– Bloque donde realicemos varias veces la misma consulta (varios
registros):
z TRANSACTION_SERIALIZABLE
Curso 2006/2007
Bases de Datos en Entornos Web
z
z
z
20
Motivación:
– Múltiples conexiones simultáneas a la base de datos.
– El establecimiento de una conexión es costoso.
Consecuencia:
– Definir cuidadosamente las transacciones.
– Establecer algún mecanismo para optimizar el uso de
conexiones Î Pool de Conexiones
Pool de Conexiones:
– Habitualmente implementado por los DataSource.
Curso 2006/2007
10
26/04/2007
Pool de Conexiones
z
z
21
Cuando no dispongamos de un DataSource que lo
implemente.
Recomendaciones de diseño:
– Definir la clase ConnectionPool como Singleton.
– Implementará la interface DataSource Æ Objeto que
devuelve el getInstance.
– Definir una clase ConnectionWrapper que implemente
Connection:
z Todos los métodos a excepción de close delegan en un
objeto Connection.
z close libera la conexión del pool.
– Creará un lista de conexiones inicial que expandirá si no
hay ninguna libre.
Curso 2006/2007
ConnectionPool - Estructura
< < In t e rf ac e > >
C o n n e c tio n
+ c o n e xio n
1
< < In t e rfa c e > >
D a t a S o u rc e
c re a te S ta te m e n t() : S ta te m e n t
p re p a re S ta te m e n t(c o n s u lta : S trin g ) : P re p a re d S ta te m e n t
c lo s e ()
...()
g e tC o n n e c tio n () : C o n n e c ti o n
C o n n e c t io n W ra p p e r
c re a te S ta te m e n t() : S ta te m e n t
p re p a re S ta te m e n t(( c o n s u lta : S trin g ) : P re p a re d S ta te m e n t
c lo s e ()
...()
C o n n e c t io n P o o l
+ pool
*
g e tC o n n e c tio n ( ) : C o n n e c tio n
r etu
t rn C o n n e ctio
ti n (c
( : C o n n e c ti
tio n P o o l)
< < s ta ti c> > ge t In s ta n c e () : D a ta S o u rc e
<<us es >>
" c lo s e " d e vu e lve e l o b je t o
C o n n e c t io n W ra p p e r a l P o o l
D r ive rM a n a g e r
c re a te C o n n e c tio n () : C o n n e c tio n
22
Curso 2006/2007
11
26/04/2007
Patrón DAO
z
z
Motivación:
– Almacenar y recuperar información persistente de diferentes
fuentes: bases de datos relacionales, LDAP, XML, etc.
– Las APIs para el acceso a datos son muy diferentes.
– La portabilidad y mantenimiento de los componentes (servlets,
EJB, ...) se ve limitada.
Solución:
– Usar un objeto DAO (Data Access Object) que abstraiga y
encapsule el acceso a la fuente de datos.
– El DAO gestiona la conexión con la fuente de datos para obtener y
almacenar la información.
23
Curso 2006/2007
Colaboración
ServletEdicion
z
Participantes:
dao : DAOCliente
getClienteByUsuario(usuario)
c : Cliente
Fuente de
datos
Obtiene los datos
new( )
return c
–
Objeto de negocio
–
DAO
–
ValueObject
–
Fuente de datos
Curso 2006/2007
getNombre()
Accede a los
datos
setCorreo( correo)
updateCliente(c)
d t Cli t ( )
getNombre()
Recupera la
información
Actualiza los datos
24
12
26/04/2007
Estrategia de Implementación
Basada en los patrones “Abstract Factory” y “Factory Method”.
Pasos:
–
Definir la interface DAO de nuestros objetos de datos
z
z
public interface ClienteDAO
{
public Cliente create (String nombre, String nif, String
correo,
String usuario, String clave) throws
DAOException
DAOException;
public Cliente findClienteByUsuario (String usuario) throws
DAOException;
public java.util.Collection findAll () throws DAOException;
public void update (Cliente c) throws DAOException;
}
25
Curso 2006/2007
Factoría Abstracta
z
Definir la factoría abstracta de objetos DAO:
public abstract class DAOFactoria
{
public abstract ClienteDAO getClienteDAO() throws DAOException;
public abstract ProductoDAO getProductoDAO() throws DAOException;
public final static int ACCESS = 1;
...
public static DAOFactoria getDAOFactoria (int tipo) {
switch (tipo) {
case ACCESS:
return new AccessDAOFactoria();
case XML:
...
}
26
Curso 2006/2007
13
26/04/2007
Factoría Concreta
z
Implementar la factoría concreta:
public class AccessDAOFactoria extends DAOFactoria{
...
public ClienteDAO getClienteDAO() {
return (ClienteDAO) new
AccessClienteDAO(ds);
}
}
–
Simplemente instancia objetos DAO concretos.
27
Curso 2006/2007
Clase DAO
z
Implementar las clases DAO concretas:
import java.sql.*;
public class AccessClienteDAO implements ClienteDAO
{
...
public Cliente create (String nombre, String nif, String
correo,
String usuario, String clave) throws
DAOException
{
Connection con = null;
try {
con = ds.getConnection();
Statement stmt = con.createStatement();
stmt.executeUpdate(...);
stmt.close();
con.close();
Cliente c = new Cliente();
c.setNombre(nombre);
...
28
Curso 2006/2007
return c;
}
14
26/04/2007
Estructura
DAOFactoria
getClienteDAO() : ClienteDAO
getProductoDAO() : ProductoDAO
<<static>> getDAOFactoria() : DAOFactoria
AccessDAOFactoria
XMLDAOFactoria
getClienteDAO() : ClienteDAO
getProductoDAO() : ProductoDAO
getClienteDAO() : ClienteDAO
getProductoDAO() : ProductoDAO
<<create>>
<<create>>
AccessClienteDAO
AccessProductoDAO
<<Interface>>
ClienteDAO
<<Interface>>
ProductoDAO
create() : Cliente
findAll() : Collection
findByUsuario() : Cliente
update()
29
Curso 2006/2007
Consecuencias
30
z
Beneficios:
– Favorece la transparencia.
– Facilita la migración de los componentes.
– Reduce la complejidad del código.
– Centraliza todo el acceso a datos en una capa.
z
Inconvenientes:
– Diseño de una jerarquía de clases.
– Introduce una nueva capa.
Curso 2006/2007
15
Descargar