T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ......

30
JDBC Aplicaciones Distribuidas

Transcript of T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ......

Page 1: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

JDBCAplicaciones Distribuidas

Page 2: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

2

Contenido

• Definición.

• Arquitectura.

• Driver.

• Conexión.

• Consultas.

• Transacciones.

• Pool de conexiones.

• Patrón DAO.

Page 3: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

3

JDBC

• 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.

Page 4: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

4

JDBC• 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ónConnection con = DriverManager.getConnection (

"jdbc:odbc:miBD", ”miLogin", ”miPassword");// Ejecuta la consultaStatement stmt = con.createStatement();ResultSet rs = stmt.executeQuery("SELECT nombre, edad FROM Empleados");// Procesa los resultadoswhile (rs.next()) {

String nombre = rs.getString(”nombre");int edad = rs.getInt(”edad");

}

Page 5: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

5

Arquitectura

Page 6: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

6

Driver

• Conjunto de clases encargadas de implementar las interfaces del API y acceder a la base de datos.

• Tipos:• Driver Tipo 1:

• Utilizan un API nativa estándar• Ejemplo: puente JDBC:ODBC

• Driver Tipo 2:• Utilizan un API nativa de la base de datos• Ejemplo: Oracle OCI

• Driver Tipo 3:• Servidor remoto con un API genérica.• Útil para aplicaciones en internet.

• Driver Tipo 4:• Totalmente desarrollado en Java• Ejemplo: Oracle Thin.

Page 7: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

7

Driver

• 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://developers.sun.com/product/jdbc/drivers

Page 8: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

8

Conexión

• 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 datos y su nombre:• jdbc:oracle:oci:dis.um.es/MiBD

• Alternativa a DriverManager: DataSource

Page 9: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

9

DataSource

• 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.

Page 10: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

10

Consultas SQL

• 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,

• 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.

Page 11: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

11

Statement

• 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.

Page 12: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

12

ResultSet

• 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.

Page 13: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

13

ResultSet

• 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()

Page 14: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

14

ResultSet – Métodos de Acceso

Tipo de dato SQL Método de Acceso CHAR String getString()

VARCHAR String getString()

LONGVARCHAR InputStream

getAsciiStream() ó

getUnicodeString()

NUMERIC java.math.BigDecimal

getBigDecimal()

DECIMAL java.math.BigDecimal

getBigDecimal()

BIT boolean getBoolean()

TINYINT byte getByte()

SMALLINT short getShort()

INTEGER int getInt()

BIGINT long getLong()

REAL float getFloat()

FLOAT double getDouble()

DOUBLE double getDouble()

BINARY byte[] getBytes()

VARBINARY InputStream

getBinayStream()

DATE java.sql.Date getDate()

TIME java.sql.Time getTime()

TIMESTAMP java.sql.TimeStamp

getTimeStamp()

Page 15: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

15

PreparedStatement

• Problema con Statement:• Cuando la consulta se realiza dentro de un bucle y varía

sólo en unos valores:• stmt.executeQuery(“SELECT * FROM Cliente WHERE

codigo = “ + i);• 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.

Page 16: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

16

PreparedStatement

• 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.

• Borrar parámetros: clearParameters()

• Ejecución:• Consulta: executeQuery().• Actualización: executeUpdate().

Page 17: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

17

Transacciones

• 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.

Page 18: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

18

Nivel de Aislamiento Transaccional

• Niveles de aislamiento:

• TRANSACTION_NONE:• Sin soporte transaccional.

• TRANSACTION_READ_UNCOMMITED:• Permite lecturas sobre datos no comprometidos.

• TRANSACTION_READ_COMMITED:• Permite lecturas sólo sobre datos comprometidos.• Nivel por defecto.

• TRANSACTION_REPEATABLE_READ.• Bloquea los datos leídos.

• TRANSACTION_SERIALIZABLE.• Sólo una transacción al mismo tiempo.

• Suelen estar disponibles read commited y serializable.

Page 19: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

19

Concurrencia

• Establecer el modo de aislamiento:• conexion.setTransactionIsolation(

Connection.TRANSACTION_SERIALIZABLE);

• Consejos de uso:• Bloque con sólo actualizaciones:

• TRANSACTION_READ_COMMITED• Bloque donde leamos varias veces el mismo registro:

• TRANSACTION_REPEATABLE_READ• Bloque en el que leamos un valor para actualizarlo:

• TRANSACTION_SERIALIZABLE• Bloque donde realicemos varias veces la misma consulta

(varios registros):• TRANSACTION_SERIALIZABLE

Page 20: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

20

Bases de Datos en Entornos Web

• 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.

Page 21: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

21

Pool de Conexiones

• 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:• Todos los métodos a excepción de close delegan en un

objeto Connection.• close libera la conexión del pool.

• Creará un lista de conexiones inicial que expandirá si no hay ninguna libre.

Page 22: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

22

ConnectionPool -Estructura

DataSource

getConnection() : Connection

<<Interface>>

ConnectionPool

getConnection() : Connectionretu rnConnection(c : ConnectionPool)<<s tatic>> getInstance() : DataSource

DriverManager

createConnection() : Connection

<<uses>>

ConnectionWrapper

createStatement() : StatementprepareStatement(consulta : String) : PreparedStatementclose()...()

*

+pool

*

Connection

createStatement() : StatementprepareStatement(consulta : String) : PreparedStatementclose()...()

<<Interface>>

1

+conexion

1

"close" devuelve el objeto ConnectionWrapper al Pool

Page 23: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

23

Patrón DAO

• 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.

Page 24: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

24

Colaboración

• Participantes:

• Objeto de negocio

• DAO

• ValueObject

• Fuente de datos

ServletEdicion dao : DAOCliente c : Cliente Fuente de

datos

getClienteByUsuario(usuario)

Obtiene los datos

new( )

return c

getNombre()

Accede a los

datos

setCorreo( correo)

updateCliente(c)getNombre()

Recupera la

información

Actualiza los datos

Page 25: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

25

Estrategia de Implementación

• Basada en los patrones “Abstract Factory” y “Factory

Method”.

• Pasos:

• Definir la interface DAO de nuestros objetos de datospublic interface ClienteDAO

{

public Cliente create (String nombre, String nif, String correo,

String usuario, String clave) throws DAOException;

public Cliente findClienteByUsuario (String usuario) throws DAOException;

public java.util.Collection findAll () throws DAOException;

public void update (Cliente c) throws DAOException;

}

Page 26: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

26

Factoría Abstracta

• 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:

...

}

Page 27: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

27

Factoría Concreta

• Implementar la factoría concreta:

• Simplemente instancia objetos DAO concretos.

public class AccessDAOFactoria extends DAOFactoria{

...

public ClienteDAO getClienteDAO() {

return (ClienteDAO) new AccessClienteDAO(ds);

}

}

Page 28: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

28

Clase DAO• 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);

...

return c;

... }

Page 29: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

29

EstructuraDAOFactoria

getClienteDAO() : ClienteDAO

getProductoDAO() : ProductoDAO

<<static>> getDAOFactoria() : DAOFactoria

AccessDAOFactoria

getClienteDAO() : ClienteDAO

getProductoDAO() : ProductoDAO

ClienteDAO

create() : Cliente

findAll() : Collection

findByUsuario() : Cliente

update()

<<Interface>>

AccessClienteDAO

<<create>>

XMLDAOFactoria

getClienteDAO() : ClienteDAO

getProductoDAO() : ProductoDAO

ProductoDAO

<<Interface>>

AccessProductoDAO

<<create>>

Page 30: T4 - JDBC - aulavirtual.um.es · • Carga de un driver: Class.forName(“acme.db.Driver”); ... • Ejecución de bloques de consultas SQL manteniendo las propiedades ACID (Atomicy-Consistency-

30

Consecuencias

• 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.

• Inconvenientes:• Diseño de una jerarquía de clases.• Introduce una nueva capa.