22
JDBC JDBC Una mini Una mini - - introducci introducci ó ó n n

Paquetes Java para JDBC - UCMgpd.sip.ucm.es/rafa/docencia/bdsi/jdbc/jdbc.pdfPaquetes Java para JDBC 2 paquetes java.sql javax.sql (m ás avanzado) La mayor parte de las aplicaciones

  • Upload
    others

  • View
    40

  • Download
    0

Embed Size (px)

Citation preview

JDBCJDBC

Una miniUna mini--introducciintroduccióónn

IntroducciIntroduccióónn

�� JDBCJDBC (Java (Java DataBaseDataBase ConnectivityConnectivity))

�� Protocolo para utilizar bases de datos Protocolo para utilizar bases de datos relacionales desde Javarelacionales desde Java

�� Se basa en la utilizaciSe basa en la utilizacióón de n de driversdrivers que que implementan un API predefinidoimplementan un API predefinido

�� Una vez seleccionado el Una vez seleccionado el driverdriver el resto del el resto del ccóódigo es independiente del SGBD digo es independiente del SGBD

Paquetes Java para JDBCPaquetes Java para JDBC

�� 2 paquetes2 paquetes

�� java.sqljava.sql

�� javax.sqljavax.sql (m(máás avanzado)s avanzado)

�� La mayor parte de las aplicaciones sLa mayor parte de las aplicaciones sóólo lo requieren requieren java.sqljava.sql

java.sqljava.sql

�� Clases e interfaces:Clases e interfaces:

Estructura JDBCEstructura JDBC

Para comunicar Java con un SGBDPara comunicar Java con un SGBD

�� Hay que conocer:Hay que conocer:

�� Fichero fFichero fíísico que contiene el sico que contiene el driverdriver ((jarjar//zipzip) (debe ) (debe estar incluido en el CLASSPATH de la aplicaciestar incluido en el CLASSPATH de la aplicacióón)n)

�� Nombre de la clase Nombre de la clase driverdriver de Java (opcional)de Java (opcional)

�� URL de conexiURL de conexióónn

�� Estos valores dependen de cada SGBD, e Estos valores dependen de cada SGBD, e incluso del incluso del driverdriver concretoconcreto

Algunos Algunos driverdriver JDBCJDBC* * MySqlMySql

o Clase o Clase DriverDriver : : com.mysql.jdbc.Drivercom.mysql.jdbc.Drivero URL de Conexio URL de Conexióón: n: jdbc:mysqljdbc:mysql://<://<hosthost>/<>/<databasedatabase> > o Fichero .o Fichero .jarjar/./.zipzip: : mysqlmysql--connectorconnector--javajava--5.0.45.0.4--bin.jarbin.jar

* * DB2DB2o Clase o Clase DriverDriver : : com.ibm.db2com.ibm.db2..jdbc.app.DB2Driverjdbc.app.DB2Drivero URL de Conexio URL de Conexióón:: n:: jdbc:db2jdbc:db2:<:<databasedatabase> > o Fichero .o Fichero .jarjar/./.zipzip: db2java.: db2java.zipzip

* * SybaseSybaseo Clase o Clase DriverDriver : : com.sybase.jdbc2com.sybase.jdbc2..jdbc.SybDriverjdbc.SybDrivero URL de Conexio URL de Conexióón: n: jdbc:sybase:Tdsjdbc:sybase:Tds:<:<hosthost>:<>:<portport>/<>/<databasedatabase>>o Fichero .o Fichero .jarjar/./.zipzip: jconn2.: jconn2.jarjar

* * OracleOracleo Clase o Clase DriverDriver : : oracle.jdbc.driver.OracleDriveroracle.jdbc.driver.OracleDrivero URL de Conexio URL de Conexióón: n: jdbc:oracle:thinjdbc:oracle:thin:@ <:@ <hosthost>:<>:<portport>:<>:<sidsid>>o Fichero .o Fichero .jarjar/./.zipzip: classes12.: classes12.zipzip

* * SQLServerSQLServero Clase o Clase DriverDriver : : com.microsoft.jdbc.sqlserver.SQLServerDrivercom.microsoft.jdbc.sqlserver.SQLServerDrivero URL de Conexio URL de Conexióón: n: jdbc:microsoft:sqlserverjdbc:microsoft:sqlserver://://localhostlocalhost:1433:1433o Fichero .o Fichero .jarjar/./.zipzip: : mssqlserver.jarmssqlserver.jar, , msbase.jarmsbase.jar, , msutil.jarmsutil.jar

* * PostgreSQLPostgreSQLo Clase o Clase DriverDriver: : org.postgresql.Driverorg.postgresql.Drivero URL de Conexio URL de Conexióón: n: jdbc:postgresqljdbc:postgresql://<://<serverserver>:<>:<portport>/<>/<databasedatabase>>o Fichero .o Fichero .jarjar/./.zipzip: : postgresql.jarpostgresql.jar

Programas Java con JDBCProgramas Java con JDBC

�� Fases:Fases:

1.1. Establecer la conexiEstablecer la conexióón con la BBDD (clase n con la BBDD (clase ConnectionConnection))

2. Crear una sentencia SQL (clase Statement o PreparedStatement)

3. Lanzar la sentencia

4. Tratar el resultado (clase ResultSet)

Fase 1: Establecer la conexiFase 1: Establecer la conexióónn(ejemplo)(ejemplo)

ConnectionConnection connectionconnection = = nullnullStatementStatement statementstatement = = nullnull;;ResultSetResultSet resultSetresultSet = = nullnull;;trytry

{{String String driverClassNamedriverClassName = "= "com.mysql.jdbc.Drivercom.mysql.jdbc.Driver";";String String driverUrldriverUrl = "= "jdbc:mysqljdbc:mysql://://localhostlocalhost/barcos";/barcos";String String useruser = "= "bertoldobertoldo";";String String passwordpassword = "= "gominolasgominolas";";Class.forName(driverClassNameClass.forName(driverClassName););connectionconnection = = DriverManager.getConnection(driverUrlDriverManager.getConnection(driverUrl, ,

useruser, , passwordpassword););..........

Fase 1.1Fase 1.1

�� Comprobamos la existencia del Comprobamos la existencia del driverdriver::

……trytry

{{String String driverClassNamedriverClassName = "= "com.mysql.jdbc.Drivercom.mysql.jdbc.Driver";";String String driverUrldriverUrl = "= "jdbc:mysqljdbc:mysql://://localhostlocalhost/barcos";/barcos";String String useruser = "= "bertoldobertoldo";";String String passwordpassword = "= "gominolasgominolas";";Class.forName(driverClassNameClass.forName(driverClassName););connectionconnection = = DriverManager.getConnection(driverUrlDriverManager.getConnection(driverUrl, ,

useruser, , passwordpassword););..........

�� Si se produce una excepciSi se produce una excepcióón debe comprobarse que el fichero fn debe comprobarse que el fichero fíísico existe y estsico existe y estáá en en el el classpathclasspath

Fase 1.2Fase 1.2

�� Nombre de la conexiNombre de la conexióón URLn URL

……

trytry

{{

……

String String driverUrldriverUrl = "= "jdbc:mysqljdbc:mysql://://localhostlocalhost/barcos";/barcos";

..........

�� La forma general de la conexiLa forma general de la conexióón para n para mysqlmysql es:es:

jdbc:mysqljdbc:mysql://<://<hosthost>/<>/<databasedatabase>>

Fase 1.3Fase 1.3

�� Abrimos la conexiAbrimos la conexióón:n:ConnectionConnection connectionconnection = = nullnullStatementStatement statementstatement = = nullnull;;ResultSetResultSet resultSetresultSet = = nullnull;;trytry

{{String String driverClassNamedriverClassName = "= "com.mysql.jdbc.Drivercom.mysql.jdbc.Driver";";String String driverUrldriverUrl = "= "jdbc:mysqljdbc:mysql://://localhostlocalhost/barcos";/barcos";String String useruser = "= "bertoldobertoldo";";String String passwordpassword = "= "gominolasgominolas";";Class.forName(driverClassNameClass.forName(driverClassName););connectionconnection = = DriverManager.getConnection(driverUrlDriverManager.getConnection(driverUrl, ,

useruser, , passwordpassword););..........

�� Normalmente los nombres de usuario y su Normalmente los nombres de usuario y su passwordpassword los introduce el usuariolos introduce el usuario

Fases 2 y 3Fases 2 y 3

�� La sentencia depende del La sentencia depende del ““dialectodialecto”” SQL del SGBD:SQL del SGBD:……StatementStatement statementstatement = = nullnull;;ResultSetResultSet resultSetresultSet = = nullnull;;trytry

{ { ……

statementstatement = = connection.createStatementconnection.createStatement();();

String String queryquery = "SELECT * FROM Batallas;";= "SELECT * FROM Batallas;";resultSetresultSet = = statement.executeQuery(querystatement.executeQuery(query););

�� La sentencia puede ser cualquier vLa sentencia puede ser cualquier váálida en SQL del SGBD (lida en SQL del SGBD (InsertInsert, , DeleteDelete, , CreateCreate TableTable, etc..), etc..)

Fase 4Fase 4

�� Tratar el resultado:Tratar el resultado:……ResultSetResultSet resultSetresultSet = = nullnull;;trytry

{ { ……

while (while (resultSet.nextresultSet.next()) {()) {// una forma de obtener una columna: por posici// una forma de obtener una columna: por posicióónnString nombre = String nombre = resultSet.getStringresultSet.getString(1);(1);// otra forma de obtener una columna: por su nombre// otra forma de obtener una columna: por su nombreDate fecha = Date fecha = resultSet.getDateresultSet.getDate("fecha");("fecha");System.out.printlnSystem.out.println("Nombre: " + nombre+ "| Fecha: "+fecha);("Nombre: " + nombre+ "| Fecha: "+fecha);

}}

ErroresErrores

�� Se pueden producir errores por:Se pueden producir errores por:

�� Fallo en la conexiFallo en la conexióónn

�� No existe la base de datos o no se tienen permisos No existe la base de datos o no se tienen permisos sobre ellasobre ella

�� Error de sintaxis en la sentencia SQLError de sintaxis en la sentencia SQL

�� OperaciOperacióón no permitidan no permitida

�� Se producirSe produciráá una excepciuna excepcióón en el programan en el programa

ExcepcionesExcepciones

……trytry

{ {

…… // las 4 fases descritas anteriormente// las 4 fases descritas anteriormente

} } catchcatch ((ClassNotFoundExceptionClassNotFoundException e) {e) {System.out.printlnSystem.out.println("No se encuentra el ("No se encuentra el driverdriver");");

} } catchcatch ((SQLExceptionSQLException E) {E) {System.out.printlnSystem.out.println("("ExcepcionExcepcion SQL: " + SQL: " + E.getMessageE.getMessage());());System.out.printlnSystem.out.println("Estado SQL: " + ("Estado SQL: " + E.getSQLStateE.getSQLState());());System.out.printlnSystem.out.println("C("Cóódigo del Error: " + digo del Error: " + E.getErrorCodeE.getErrorCode());());

} }

Liberar Recursos Liberar Recursos

� Aunque no se llame a Connection.close, cuando la conexión sea eliminada por el garbage collector, el método finalize de la clase que implementa Connection, invocará al método close� Cuando se cierra una conexión, cierra todos sus Statements asociados� Cuando se cierra un Statement, cierra todos sus ResultSets asociados

� Pero:� En una aplicación multi-thread que solicita muchas conexiones por

minuto (ej.: una aplicación Internet)� Puede haber bugs en algunos drivers, de manera que no cierren los

Statements asociados a una conexión o los ResultSets asociados a un Statement

Es imprescindible cerrar las conexiones tan pronto como se pueda

Liberando recursosLiberando recursos

……trytry

{ { …… // las 4 fases descritas anteriormente// las 4 fases descritas anteriormente

} } catchcatch …………finallyfinally {{

trytry {{if (if (resultSetresultSet != != nullnull) ) resultSet.closeresultSet.close();();if (if (statementstatement != != nullnull) ) statement.closestatement.close();();if (if (connectionconnection != != nullnull) ) connection.closeconnection.close();();

} } catchcatch ((SQLExceptionSQLException e) { e) { e.printStackTracee.printStackTrace();(); }}

}}

PreparedStatementPreparedStatement

�� Cada vez que se envía una query a la BD, ésta:� La analiza sintácticamente� Construye un plan para ejecutarla

� Si tenemos un bucle en el que repetidamente se lanza la misma query con distintos parámetros � ineficiencia usando Statement

� En este tipo de situaciones, es mejor usar PreparedStatement

Ejemplo Ejemplo PreparedStatementPreparedStatement

�� Ejemplo:Ejemplo:

// establecer la conexi// establecer la conexióón n ……

String [] String [] nombreBatallasnombreBatallas={={……..};..};Date [] Date [] fechaBatallasfechaBatallas={={……..}; // de la misma long. que el anterior..}; // de la misma long. que el anteriorString query = "INSERT INTO Batallas (nombre,fecha) VALUES (?,?);";preparedStatement = connection.prepareStatement(queryString);/* insertamos las batallas en la BD */for (int i=0; i<nombreBatallas.length; i++) {

// rellenamos el parámetro 1 y 2 preparedStatement.setString(1, nombreBatallas[i]);preparedStatement.setDate(2, balances[i]);// ejecutar la consultaint filas = preparedStatement.executeUpdate();if (filas != 1) { throw new SQLException(“Problemas insertando ”+ nombreBatallas[i]);

}…

Ejemplo Ejemplo PreparedStatementPreparedStatement (II)(II)

�� En el ejemplo anterior:En el ejemplo anterior:

�� SSóólo se hace el anlo se hace el anáálisis sintlisis sintááctico una vezctico una vez

�� Se hace un Se hace un úúnico plan de ejecucinico plan de ejecucióónn

�� Mejor eficiencia con respecto a Mejor eficiencia con respecto a StatementStatement

Lo que no hemos contadoLo que no hemos contado

�� Hemos visto Hemos visto java.sqljava.sql pero no pero no javax.sqljavax.sql�� Utiliza el tipo Utiliza el tipo DataSourceDataSource para cargar el para cargar el driverdriver �� mmáás s

configurableconfigurable

�� Uso del Uso del ““pool de conexionespool de conexiones”” para mpara múúltiples accesos a la ltiples accesos a la misma base de datosmisma base de datos

�� Usar transacciones no atUsar transacciones no atóómicas:micas:�� Cambiar a Cambiar a connection.setAutoCommit(falseconnection.setAutoCommit(false););

�� Acabar con Acabar con connection.commitconnection.commit() si todo va bien o() si todo va bien o

�� Con Con connection.rollbackconnection.rollback() si hay alg() si hay algúún probleman problema

�� Problemas de concurrenciaProblemas de concurrencia

�� ScrollableScrollable ResulSetsResulSets, sentencias , sentencias batchbatch, etc., etc., etc., etc.