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

Anuncio
escuela técnica superior
de ingeniería informática
Diseño de la
capa de datos.
Acceso a datos con JDBC
Departamento de
Lenguajes y Sistemas Informáticos
Ingeniería del Software II
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
Introducción
• Problema:
• ¿Cómo separamos la lógica de
negocio del acceso a los datos?
• Solución:
• Utilizaremos el patrón DAO (“Core
J2EE Patterns” ) para desacoplar el
acceso a datos de la lógica de
negocio.
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
• Usaremos JDBC para acceder al
SGBD
Capa de acceso a datos
Lógica de negocio
Capa de datos
(DAO)
MySQL Connector/J
(Driver JDBC)
MySQL
• Herramientas:
• MySQL
• MySQL Connector/J
(driver tipo 4 para
MySQL)
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
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)
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
API
JDBC
Driver Manager
JDBC
Driver
JDBC
DBMS
Bridge
JDBC/ODBC
Driver
ODBC
DBMS
Modo de trabajo en JDBC
Cargar driver
Obtener conexión
Obtener conexión
Crear sentencia JDBC
Lanzar consulta
Lanzar consulta
Ejecutar sentencia
Tratar resultado
Cerrar conexión
Cerrar conexión
Descargar driver
Liberar recursos
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
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
Cargar driver
Obtener conexión
Obtener conexión
Lanzar consulta
Lanzar consulta
Cerrar conexión
Cerrar conexión
Descargar driver
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
Cargar/Descargar el driver
• Cargar el driver:
Driver dBDriver = (Driver) Class.forName(driverName)
.newInstance();
DriverManager.registerDriver(dBDriver);
• Descargar el driver:
DriverManager.deregisterDriver(dBDriver);
• Ejemplos de nombres de driver:
•
com.microsoft.jdbc.sqlserver.SQLServerDriver
(SQLServer)
•
com.mysql.jdbc.Driver (MySQL Connector/J)
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
• Ejemplos
Identificación del SGBD
• Se usa una URI para identificar al DBMS
jdbc:mysql://127.0.0.1:3306/POS
• Transporte: jdbc
• Tipo de base de datos: mysql
• Nombre del servidor: 127.0.0.1
• Puerto: 3306
• Base de datos: POS
Obtener/liberar conexiones
<<interface>>
Connection
+close()
+prepareStatement(String s): PreparedStatement
• Una conexión con la base de datos se establece usando un
driver ya registrado:
Connection conn = DriverManager.getConnection(dBUri,
username, password);
• Liberar conexión:
conn.close();
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
Cargar driver
Obtener conexión
Obtener conexión
Crear sentencia JDBC
Lanzar consulta
Lanzar consulta
Ejecutar sentencia
Tratar resultado
Cerrar conexión
Cerrar conexión
Descargar driver
Liberar recursos
Lanzar consultas
Crear sentencia JDBC
Ejecutar sentencia
Tratar resultado
Liberar recursos
Crear una sentencia JDBC
<<interface>>
Connection
Crear sentencia JDBC
Ejecutar sentencia
Tratar resultado
Liberar recursos
+close()
+prepareStatement(String s): PreparedStatement
<<interface>>
PreparedStatement
+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
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
PreparedStatement
• Se crean usando el método
prepareStatement de una conexión
PreparedStatement con.prepareStatement(String s)
• El parámetro s hace referencia a la consulta
SQL, en la que pueden aparecer parámetros
String sql = "DELETE FROM Customer WHERE (CUSTOMERID = ?)";
• De existir parámetros, usamos los métodos
setXXX(x,y) para darles valor (x identifica al
parámetro, y al valor que toma)
Métodos setXXX(x,y)
Método de PreparedStatement
Tipo del valor y
setBoolean(x,y)
boolean
setByte(x,y)
byte
setDate(x,y)
Date
setDouble(x,y)
double
setFloat(x,y)
float
setInt(x,y)
int
setLong(x,y)
long
setString(x,y)
String
setTime(x,y)
Time
setTimeStamp(x,y)
TimeStamp
setObject(x,y)
Object
…
…
Ejemplos
PreparedStatement stmt = null;
String sql = "DELETE FROM Customer WHERE (CUSTOMERID = ? ) ";
stmt = conn.prepareStatement(sql); //conn es una conexión válida
stmt.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”);
Ejecución de sentencias
Crear sentencia JDBC
Ejecutar sentencia
Tratar resultado
Liberar recursos
<<interface>>
PreparedStatement
+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
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, …
Tratar el resultado
Crear sentencia JDBC
<<interface>>
Resulset
Ejecutar sentencia
Tratar resultado
Liberar recursos
+next(): boolean
+first(): boolean
+getXXX(s: String): XXX
+close()
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)
Métodos getXXX(s)
Método de ResulSet
Tipo Java
getBoolean(s)
boolean
getByte(s)
byte
getDate(s)
Date
getDouble(s)
double
getFloat(s)
float
getInt(s)
int
getLong(s)
long
getString(s)
String
getTime(s)
Time
getTimeStamp(s)
TimeStamp
getObject(s)
Object
…
…
Liberar recursos
<<interface>>
PreparedStatement
Crear sentencia JDBC
Ejecutar sentencia
+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()
Tratar resultado
<<interface>>
Resulset
Liberar recursos
+next(): boolean
+first(): boolean
+getXXX(s: String): XXX
+close()
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();
Ejemplos de consultas
<<Class Model>>
Customer
-customerID
-name
-surname
<<Physical Data Model>>
Customer
OID = <<PK>>
customerID
name
surname
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));
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();
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();
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,
stmt.setString(2,
stmt.setString(3,
stmt.setString(4,
oid);
c.getCustomerID());
c.getName());
c.getSurname());
stmt.executeUpdate();
stmt.close();
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();
Índice
• Introducción
• JDBC
•
•
•
•
Cargar/Descargar el driver
Obtener/liberar conexiones
Lanzar consultas
Tratamiento de las excepciones
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
Cargar driver
...
try {
// Aquí va el código para cargar el driver
} catch(Exception e) {
System.err.println(e.getMessage());
}
...
Métodos jdbc
Captura de las excepciones
...
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());
}
...
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();}
}
...
¡Gracias!
• ¿Podemos mejorar esta lección?
Mándanos un email a [email protected]
Visita la web: www.lsi.us.es
Descargar