Diseño de la capa de datos. Acceso a datos con JDBC

39
Departamento de Departamento de Lenguajes y Sistemas Informáticos Lenguajes y Sistemas Informáticos escuela técnica superior de ingeniería informática Ingeniería del Software II Diseño de la capa de datos. Acceso a datos con JDBC

Transcript of Diseño de la capa de datos. Acceso a datos con JDBC

Page 1: Diseño de la capa de datos. Acceso a datos con JDBC

Departamento deDepartamento deLenguajes y Sistemas InformáticosLenguajes y Sistemas Informáticos

escuela técnica superiorde ingeniería informática

Ingeniería del Software II

Diseño de la capa de datos.

Acceso a datos con JDBC

Page 2: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

Page 4: Diseño de la capa de datos. Acceso a datos con JDBC

Capa de acceso a datos

MySQL Connector/J(Driver JDBC)

MySQL

Capa de datos (DAO)

Lógica de negocio• Herramientas:

• MySQL

• MySQL Connector/J (driver tipo 4 para MySQL)

Page 5: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

Page 6: Diseño de la capa de datos. Acceso a datos con JDBC

Introducción

• JDBC es un API (java.sql.*) proporcionada por Sun para lanzar sentencias SQL a bases de datos relacionales (estándar ANSI SQL-2)

• Los desarrolladores de SGBD proporcionan la implementación de esa interfaz (Drivers)

Page 7: Diseño de la capa de datos. Acceso a datos con JDBC

Arquitectura

• Tipo 1: (JDBC-ODBC Bridge) delegan el acceso a datos a una API ODBC

• Tipo 2: Usan código nativo para el acceso a datos y proveen un envoltorio de clases java para las llamadas al driver. Es por tanto específico para una plataforma

• Tipo 3: Driver 100% Java / Protocolo nativo. Se comunica con el SGBD utilizando el protocolo de red nativo del servidor

• Tipo 4: Driver 100% Java / Protocolo independiente. Hace las peticiones de datos a un intermediario en un protocolo de red independiente del SGBD DBMS

DriverJDBC

BridgeJDBC/ODBC

Driver ManagerJDBC

APIJDBC

DBMS

DriverODBC

Page 8: Diseño de la capa de datos. Acceso a datos con JDBC

Modo de trabajo en JDBC

Cargar driver

Descargar driver

Obtener conexión

Lanzar consulta

Cerrar conexión

Obtener conexión

Lanzar consulta

Cerrar conexión

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

Page 9: Diseño de la capa de datos. Acceso a datos con JDBC

JDBC

• Necesitaré:• Alguien que represente a un gestor de

drivers: DriverManager• Alguien que represente a las

conexiones: Connection• Alguien que represente a las sentencias: PreparedStatment

• Alguien que represente a los resultados: ResultSet

Page 10: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

Cargar driver

Descargar driver

Obtener conexión

Lanzar consulta

Cerrar conexión

Obtener conexión

Lanzar consulta

Cerrar conexión

Page 11: Diseño de la capa de datos. Acceso a datos con JDBC

Cargar/Descargar el driver

• Cargar el driver:

Class

+static forName(): Class+newInstance(): Object

DriverManager

+static registerDriver(dbDriver: Driver)+static deregisterDriver(dbDriver: Driver)+static getConnection(dBUri: String, username: String, password: String): Connection

Page 12: Diseño de la capa de datos. Acceso a datos con JDBC

Cargar/Descargar el driver

• Cargar el driver:

• Descargar el driver:

• Ejemplos de nombres de driver:• com.microsoft.jdbc.sqlserver.SQLServerDriver

(SQLServer)• com.mysql.jdbc.Driver (MySQL Connector/J)

Driver dBDriver = (Driver) Class.forName(driverName) .newInstance();DriverManager.registerDriver(dBDriver);

DriverManager.deregisterDriver(dBDriver);

Page 13: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

• Ejemplos

Page 14: Diseño de la capa de datos. Acceso a datos con JDBC

Identificación del SGBD

• Se usa una URI para identificar al DBMS

• Transporte: jdbc• Tipo de base de datos: mysql• Nombre del servidor: 127.0.0.1• Puerto: 3306• Base de datos: POS

jdbc:mysql://127.0.0.1:3306/POS

Page 15: Diseño de la capa de datos. Acceso a datos con JDBC

Obtener/liberar conexiones

• Una conexión con la base de datos se establece usando un driver ya registrado:

• Liberar conexión:

Connection conn = DriverManager.getConnection(dBUri, username, password);

conn.close();

Connection<<interface>>

+close()+prepareStatement(String s): PreparedStatement

Page 16: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

Cargar driver

Descargar driver

Obtener conexión

Lanzar consulta

Cerrar conexión

Obtener conexión

Lanzar consulta

Cerrar conexión

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

Page 17: Diseño de la capa de datos. Acceso a datos con JDBC

Lanzar consultas

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

Page 18: Diseño de la capa de datos. Acceso a datos con JDBC

Crear una sentencia JDBC

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

PreparedStatement<<interface>>

+setBoolean(x: int, y: boolean)+setByte(x: int, y: byte)+setDate(x: int, y: Date)+setDouble(x: int, y: double)+setString(x: int, y: String)+executeQuery(): ResultSet+executeUpdate(): int+execute(): boolean

Connection<<interface>>

+close()+prepareStatement(String s): PreparedStatement

Page 19: Diseño de la capa de datos. Acceso a datos con JDBC

Interfaces proporcionadas por JDBC• Statement

• Para la ejecución de sentencias SQL estáticas en tiempo de ejecución

• PreparedStatement• Para la ejecución de sentencias SQL, se

precompilan (más rápidas) y aceptan parámetros de entrada en tiempo de ejecución

• CallableStatement• Para la ejecución de procedimientos almacenados

en la base de datos

Page 20: Diseño de la capa de datos. Acceso a datos con JDBC

PreparedStatement• Se crean usando el método prepareStatement de una conexión

• El parámetro s hace referencia a la consulta SQL, en la que pueden aparecer parámetros

• De existir parámetros, usamos los métodos setXXX(x,y) para darles valor (x identifica al parámetro, y al valor que toma)

PreparedStatement con.prepareStatement(String s)

String sql = "DELETE FROM Customer WHERE (CUSTOMERID = ?)";

Page 21: Diseño de la capa de datos. Acceso a datos con JDBC

Métodos setXXX(x,y)

ObjectsetObject(x,y)

Tipo del valor yMétodo de PreparedStatement

TimeStampsetTimeStamp(x,y)

intsetInt(x,y)longsetLong(x,y)

floatsetFloat(x,y)doublesetDouble(x,y)

StringsetString(x,y)TimesetTime(x,y)

……

DatesetDate(x,y)bytesetByte(x,y)booleansetBoolean(x,y)

Page 22: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplos

PreparedStatement stmt = null;String sql = "DELETE FROM Customer WHERE (CUSTOMERID = ? ) "; stmt = conn.prepareStatement(sql); //conn es una conexión válidastmt.setString(1, customerID);

PreparedStatement stmt = null;String sql = "SELECT * FROM Customer";stmt = conn.prepareStatement(sql); //conn es una conexión válida

PreparedStatement stmt = null;String sql = "INSERT INTO CUSTOMER (OID, CUSTOMERID, NAME, SURNAME)”+ “ VALUES (?, ?, ?, ?)";stmt = conn.prepareStatement(sql);stmt.setString(1, “33423”);stmt.setString(2, “Customer 1”);stmt.setString(3, “Name 1”);stmt.setString(4, “Name 2”);

Page 23: Diseño de la capa de datos. Acceso a datos con JDBC

Ejecución de sentencias

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

PreparedStatement<<interface>>

+setBoolean(x: int, y: boolean)+setByte(x: int, y: byte)+setDate(x: int, y: Date)+setDouble(x: int, y: double)+setString(x: int, y: String)+executeQuery(): ResultSet+executeUpdate(): int+execute(): boolean

Page 24: Diseño de la capa de datos. Acceso a datos con JDBC

Métodos de PreparedStatement• ResultSet executeQuery()

• Ejecuta una sentencia de tipo “SELECT”, devuelve un objeto ResultSet con los resultados de la consulta

• int executeUpdate()• Ejecuta una sentencia de tipo “INSERT”,

“UPDATE” o “DELETE”. Devuelve el número de registros insertados/actualizados/borrados

• boolean execute()• Para la ejecución de procedimientos almacenados

en la base de datos, …

Page 25: Diseño de la capa de datos. Acceso a datos con JDBC

Tratar el resultado

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

Resulset<<interface>>

+next(): boolean+first(): boolean+getXXX(s: String): XXX+close()

Page 26: Diseño de la capa de datos. Acceso a datos con JDBC

Tratar el resultado

• El resultado de ejecutar un SELECT se devuelve en un objeto de tipo ResulSet

• Métodos de interés:• next(): para iterar por las filas del ResulSet (la primera llamada nos posiciona en la primera fila de resultados)

• first(): para ir al principio del ResulSet• getXXX(s): devuelve el valor, dentro de

una fila, especificado por s (índice o nombre de columna)

Page 27: Diseño de la capa de datos. Acceso a datos con JDBC

Métodos getXXX(s)

ObjectgetObject(s)

Tipo JavaMétodo de ResulSet

TimeStampgetTimeStamp(s)

intgetInt(s)longgetLong(s)

floatgetFloat(s)doublegetDouble(s)

StringgetString(s)TimegetTime(s)

……

DategetDate(s)bytegetByte(s)booleangetBoolean(s)

Page 28: Diseño de la capa de datos. Acceso a datos con JDBC

Liberar recursos

Crear sentencia JDBC

Ejecutar sentencia

Tratar resultado

Liberar recursos

Resulset<<interface>>

+next(): boolean+first(): boolean+getXXX(s: String): XXX+close()

PreparedStatement<<interface>>

+setBoolean(x: int, y: boolean)+setByte(x: int, y: byte)+setDate(x: int, y: Date)+setDouble(x: int, y: double)+setString(x: int, y: String)+executeQuery(): ResultSet+executeUpdate(): int+execute(): boolean+close()

Page 29: Diseño de la capa de datos. Acceso a datos con JDBC

Liberar recursos

• Liberar los objetos usados del tipo:• PreparedStatement• ResulSet (si hemos lanzado un SELECT)

PreparedStatement stmt = null;ResulSet result = null;...stmt.close();result.close();

Page 30: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplos de consultas

OID = <<PK>>customerIDnamesurname

Customer

CREATE TABLE CUSTOMER ( OID varchar(50) NOT NULL, CUSTOMERID varchar(50) NOT NULL, NAME varchar(50) NOT NULL, SURNAME varchar(50) NOT NULL,PRIMARY KEY(OID));

<<Class Model>> <<Physical Data Model>>

-customerID-name-surname

Customer

Page 31: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplo de Select (1)

PreparedStatement stmt = null; ResultSet result = null; Customer c = null; String sql = "SELECT * FROM CUSTOMER WHERE (CUSTOMERID = ? ) ";

stmt = conn.prepareStatement(sql); //conn es una conexión válida stmt.setString(1, customerID); result = stmt.executeQuery();

result.next(); c = new Customer(); c.setCustomerID(result.getString("CUSTOMERID")); c.setName(result.getString("NAME")); c.setSurname(result.getString("SURNAME"));

result.close(); stmt.close();

Page 32: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplo de Select (2)

PreparedStatement stmt = null; List searchResults = new LinkedList(); ResultSet result = null; String sql = "SELECT * FROM Customer"; stmt = conn.prepareStatement(sql); //conn es una conexión válida stmt.executeQuery(); result = stmt.executeQuery();

while (result.next()) { Customer temp = new Customer(); temp.setCustomerID(result.getString("customerID")); temp.setName(result.getString("name")); temp.setSurname(result.getString("surname")); searchResults.add(temp); }

result.close(); stmt.close();

Page 33: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplo de Insert

PreparedStatement stmt = null; String oid = UIDGenerator.getInstance().getKey();

String sql = "INSERT INTO CUSTOMER (OID, CUSTOMERID, NAME, SURNAME)”+ “ VALUES (?, ?, ?, ?)"; stmt = conn.prepareStatement(sql);

stmt.setString(1, oid); stmt.setString(2, c.getCustomerID()); stmt.setString(3, c.getName()); stmt.setString(4, c.getSurname());

stmt.executeUpdate();

stmt.close();

Page 34: Diseño de la capa de datos. Acceso a datos con JDBC

Ejemplo de Delete

String sql = "DELETE FROM Customer WHERE (CUSTOMERID = ? ) "; PreparedStatement stmt = null; stmt = conn.prepareStatement(sql); //conn es una conexión válida stmt.setString(1, customerID);

stmt.executeUpdate();

stmt.close();

Page 35: Diseño de la capa de datos. Acceso a datos con JDBC

Índice

• Introducción• JDBC

• Cargar/Descargar el driver• Obtener/liberar conexiones• Lanzar consultas• Tratamiento de las excepciones

Page 36: Diseño de la capa de datos. Acceso a datos con JDBC

Tratamiento de excepciones

• Se pueden producir una excepción:• Al cargar el driver (Class.forName):

• InstantiationException• IllegalAccessException• ClassNotFoundException

• Al utilizar los métodos definidos en las interfaces que proporciona JDBC (JDBC usa excepciones para el tratamiento de los errores) :• SQLException

Page 37: Diseño de la capa de datos. Acceso a datos con JDBC

Captura de las excepciones

...try { // Aquí va el código para cargar el driver} catch(Exception e) { System.err.println(e.getMessage());}...

...try {// Aquí va el código que podría generar la excepción.} catch(SQLException e) { // Descripción del error System.out.println("Message: " + e.getMessage()); // identificación del error System.out.println("SQLState: " + e.getSQLState()); // Código de error del vendedor System.out.println("ErrorCode: " + e.getErrorCode());}...

Carg

ar

dri

ver

Méto

do

s jd

bc

Page 38: Diseño de la capa de datos. Acceso a datos con JDBC

Métodos JDBC (liberación recursos)• A veces es necesario liberar recursos, se

produzca o no una excepción

...PreparedStatement stmt;ResultSet result;Connection conn;...try {// Aquí va el código que podría generar la excepción.// y que hace uso de stmt, result y conn} catch (SQLException e) { System.out.println("Message: " + e.getMessage()); System.out.println("SQLState: " + e.getSQLState()); System.out.println("ErrorCode: " + e.getErrorCode());} finally { conn.close(); if (result != null) {result.close();} if (stmt != null) {stmt.close();} }...

Page 39: Diseño de la capa de datos. Acceso a datos con JDBC

¡Gracias!

• ¿Podemos mejorar esta lección?

Mándanos un email a [email protected]

Visita la web: www.lsi.us.es