Sunteți pe pagina 1din 23

Manejar Conexiones a Bases de Datos con JDBC 3.

Manejar Conexiones a Bases de Datos con JDBC 3.0

Introducin al Tutorial
Deber a leer este Tutor ial? Este tutorial presenta los diferentes conceptos implicados en el establecimiento y control de una conexin con bases de datos dentro de una aplicacin Java usando Java Database Connection (JDBC). Est dirigido principalmente a desarrolladores que quieren entender que "qu hay detrs de la escena" cuando usan una base de datos desde dentro de una aplicacin Java Este tutorial asume que ests familiarizado con el lenguaje de programacin Java. Sobre qu va este Tutorial? Este tutorial demuestra cmo conectar con una base de datos usando JDBC. Aunque parece inocuo, este punto es realmente un obstculo tanto para novatos como para veteranos en Java. Este tutorial explicar cmo una aplicacin Java dentro de una JVM descubre y se comunica con una base de datos, empezando con el tradicional driver JDBC y los objetos Driver Manager. Despus de varios ejemplos que demuestran los cuatro tipos diferentes de dr ivers JDBC, el tutorial se mueve sobre una explicacin de objetos DataSource que usan JNDI. Tambin se incluye una discusin sobre JNDI, y cmo unir, usar, reunir y borrar el objeto DataSource. Finalmente, se presentan y demuestran los conceptos de almacen de conexiones, y especficamente los objetos PooledConnection. El tutorial concluye con una discusin de problemas de ajuste que normalmente se nos pasan cuando desarrollamos aplicaciones de conectividad de base de datos. Herramientas Aunque el tutorial proporciona numerosos fragmentos de cdigo para reflejar conceptos y mtodos descritos en el texto, la mayora de la gente aprender mejor trabajando realmente a travs de los ejemplos. Para trabajar con los ejemplos, necesitars tener instaladas y funcionando las siguientes herramientas: Un editor de texto: los ficheros fuente Java son simplemente texto, por eso para crearlos y leerlos, necesitamos un editor de texto. Si tienen acceso a un IDE Java, puedes usarlo, pero algunas veces ocultan muchos detalles. Un entor no de desarrollo Java, como el Java2 S DK, que est disponible en http://java.sun.com/j2se/1.4/ . El Java2 S DK, Standard Edition versin 1.4, incluye las extensiones estndard JDBC as como JNDI, mbos son necesarios para algunos de los ejemplos posteriores de este tutorial Una base de datos compatible SQL: los ejemplos de este tutorial usan una amplia variedad de bases de datos para ayudarnos a demostrar cmo se puede hacer programacin JDBC independiente de la base de datos. Un driver JDBC: como el API JDBC est predominantemente compuesto por interfaces, necesitamos obtener una implementacin de un driver JDBC real para poder conectar realmente con una base de datos usando JDBC. Si nuestra base de datos (o nuestra maleta) no permite el uso de JDBC, siempre podemos usar el dirver puente JDBC-ODBC para conectar con cualquier base de datos (o fuente de datos) que sopor ta el protocolo ODBC.

Pgina 2 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Arquitectura de la Aplicacin
Arquitecturar Nuestro Sistema Uno de los problemas de diseo ms importantes cuando desarrollamos una aplicacin de bases de datos en Java es la arquitectura general del sistema; en par ticular, cuntos componentes diferentes deberamos desplegar. Tradicinonalmente, esto est caracterz ado por el nmero de capas que requiere la aplicacin. Hay dos modelos arquitecturales bsicos que pueden describir un sistema: el modelo de dos capas y el modelo de n-capas. Antes de entrar en los detalles del manejo de conexiones a bases de datos desde una aplicacin Java, necesitamos explicar estos dos modelos. Cada modelo tiene sus propias ventajas e inconvenientes; cada uno tambin requiere que ciertos componentes se configuren apropiadamente, y , como resultado, cada uno funciona mejor en entor nos diferentes. Las dos siguientes secciones explican en ms detalle cada uno de los dos modelos arquitecturales. El Modelo de Dos Capas El modelo de dos capas es el marco de trabajo tradicional cliente -servidor; tiene una capa cliente y una capa servidor. Este modelo simple requiere que el cliente tenga cuidado especfico de la base de datos. As, por ejemplo, el cliente necesita cdigo especfico de la base de datos resultando en un acoplamiento fuer te entre las dos capas. Este acoplamiento fuerte tienes varias ventajas. Primero, puede reducir el tiempo de desarrollo debido al hecho de que todo el sistema es considerablemente ms simple y ms pequeo. Segundo, el acoplamiento fuerte puede mejorar potencialmente el rendimiento del sistema ya que el cliente puede fcilmente aprovecharse de las funcionalidades especficas del servidor que podran no estar disponibles para sistemas con un acoplamiento ms ligero. Por otro lado, este acoplamiento fuer te puede provocar varios problemas. El mas notable, el mantenimiento del sistema se puede volver ms dficil porque los cambios en el servidor pueden romper al cliente y viceversa. Adems, si la base de datos cambia, todo el cdigo del cliente deber ser modificado. Si el cliente est altamente distribuido, la propagaci n de los cambios en el sistema puede ser dficil, y en algunos escenarios imposible. Como resultado, las aplicaciones de dos capas pueden ser tiles en un entorno de LAN cor porativa donde el completo control de todos los clientes se consigue, o al inicio, o en el estado prototipal de un proyecto donde diferentes opciones estn siendo evaluadas. El Modelo de n-Capas El modelo de n-capas tiene una capa cliente, al menos una capa servidor, y al menos una cada intermedia. Debido a la capa extra, muchos de los problemas que afectan a los modelos de dos capas no afectarn. Por ejemplo, la capa media ahora mentiene informacin de la conexin a la base de datos. Esto significa que los clientes slo tienen que conocer la capa media. Como la capa media generalmente est operando en la misma localizacin fsica que el servidor (por ejemplo, ambos componentes pueden estar detrs del mismo firewall), mantener la capa media es considerablemente ms sencillo que mantener cientos de instalaciones clientes. Otra ventaja de la aproximacin de n-capas es que todo el sistema se puede escalar fcilmente para manejar ms usuarios.Todo lo que necesitamos hacer es aadir ms capas medias o ms capas servidores, dependiendo de los resultados de las operaciones de perfilado. Como l as capas intermedias normalmente se implementan usado ser vidores Web -- usando tecnologas JavaServer Pages y Servlets -- es muy sencillo aadir balance de carga o incluso nuevos componentes hardware. Sin embargo, no todo es de color rosa, ya que la capa extra intoduce complejidad adicional en todo el sistema. Esto significa ms cdigo, ms duro de probar y potencialmente ms dficil de encontrar sus errores. Afortunadamente, el lenguaje Java proporciona muchos de los componentes necesarios, pre-constr uidos. para construir aplicaciones de n-capas viables. Adems, este modelo se presta a si mismo el fcil sopor te de autentificacin e internacionalizacin, ya que la capa media controla el flujo de informacin y proporciona localizacin natural para manjear to do lo que concierne al manejo de seguridad y la localizacin.

Pgina 3 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Fundamentos de los Drivers JDBC


Introduccin a los Dr ivers JDBC Una inspeccin casual del API JDBC muestra rpidamente la dominacin de los interfaces dentro del API, lo que podra llevar al usuario a preguntarse dnde se realiza el trabajo. Realmente esta es slo una aproximacin que tocan los desarrolladores JDBC porque la implementacin real es la proporcionada por los vendedores de Drivers JDBC, que a su vez proporcionan las clases que implementan los interfaces necesarios. Esta aproximacin presenta la competicin que proporciona al consumidor ms opciones, y para la mayor parte, produce mejor software. Con todos los drivers disponibles. elegir uno puede ser dficil. Aforturnadamente, Sun Microsystems mantiene una base de datos con ms de 150 drivers JDBC de una amplia variedad de vendedores. Esta debera ser la primera parada despus de seleccionar una base de datos. Desde una perspectiva de programacin, hay dos clases principales respnsables para el establecimiento de una conexin con una base de datos. La primera clase es Driver Manager, que es una de las clases que realmente proprociona el API JDBC. DriverManager es responsable de manejar un almacen de drivers registrados, esencialmente abstrayendo los detalles del uso de un driver para que el programador no tenga que tratar con ellos directamente. La segunda clase es la clase real del Driver JDBC. Estas son proporcionadas por vendedores independientes. La clase Driver JDBC es la responsable de establecer la conexin con la base de datos y de manejar todas las comunicaciones con la base de datos. Los drivers JDBC vienen en cuatro tipos diferentes Registrar un Dr iver JDBC El primer paso en el proceso de crear una conexin entre una aplicacin Java y una base de datos es el registro de un driver JDBC con la Mquina Virtual Java (JVM) en la que se est ejecutando la aplicacin Java. En el mecanimso de conexin tradicional (en oposicin al mecanismo de conexin del DataSource) la conexin y todas las comunicacin con la base de datos son controladas por un objeto DriverManager. Para establecer una conexin, se debe registrar un driver JDBC adecuado para la base de datos objetiv o con el objeto Driver Manager. La especificacin JDBC, dice que se supone que los dir vers JDBC se registran automticamente a s mismos con el objeto DriverManager cuando se cargan en la JVM. Por ejemplo, el siguiente fragmento de cdigo usa un inicializador esttico para primero crear un ejemplar del driver JDBC persistentjava y luego resgistrarlo con el DriverManager:
static { java.sql.DriverManager.registerDriver(new com.persistentjava.JdbcDriver()) ; }

Registrar un driver es tan simple como cargar la clase del driver en la JVM, lo que puede hacerse de muchas maneras. Una forma es con el ClassLoader Class.forName(com.persistentjava.JdbcDriver). Otro mtodo, que no es tan bien conocido, usa la propidad del sistema jdbc.drivers. Este mtodo se puede usar de tres formas distintas: Desde la lnea de comandos: java -Djdbc.drivers=com.persistentjava.JdbcDriver Connect Dentro de la palicacin Java: System.setProperty("jdbc.drivers","com.persistentjava.JdbcDriver") ; Seleccionando la propiedad jdbc.drivers en el fichero de propiedades del sistema, que generalmente depende del sistema. Separando los drivers con una coma, se pueden registrar varios drivers usando la tcnica de la propiedad del sistema mostrada arriba. Uno de los beneficios de usar la tcnica de la propiedad del sistema es que se los drivers se pueden intercambiar fcilmente sin modificar ningn cdigo (o al menos con unos mnimos cambios). Si se registran varios drivers, su orden de precedencia es: Drivers JDBC registrados por la propiedad jdbc.drivers en la inicializacin de la JVM, y Drivers JDBC cargados dinmicamente.

Pgina 4 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Como la propiedad jdbc.drivers slo se chequea una vez durante la primera invocacin del mtodo DriverManager(), es importante asegurarse de que todos los drivers estn registrados correctamente antes de establecer la conexin con la base de datos. Sin embargo, no todas las JVM estn creadas igual, y algunas de ellas no siguen la especificacin JVM. Como resultado, los inicializadores estticos no siempre funcionan como hemos dibujado. Esto resulta en mltiples formas de registrar un driver JDBC, incluyendo: Class.forName("com.persistentjava.JdbcDriver").newInstance(); DriverManager.registerDriver(new com.persistentjava.JdbcDriver()) ; Estas alternativas deberan funcionar bien en todas las JVMs, por eso deberamos sentirnos agusto usndolas a lo largo del amplio conjunto de JVM disponibles. Un problema final es que Class.forname() puede lanzar una ClassNotFoundException, por eso debemos envolver el cdigo de registro en un manejador de excepcin apropiado. URLs de Dr ivers JDBC Una vez que un Driver JDBC se ha registrado con el DriverManager, puede usarse para establecer una conexin a una base de datos. Pero cmo selecciona DriverManager el driver correcto, dado que puede haber realmente rigstrados cualquier nmero de drivers? (Recuerda, una sla JVM podra soportar mltiples aplicaciones concurrentes, que podran conectarse con diferentes bases de datos con diferentes drivers). La tcnica es bastante simple: cada driver JDBC usa una URL JDBC especfica (que tiene el mismo formato que una direccin Web) como un significado de auto-identificacin. El formato de la URL es correcto y probablemente parece familiar: jdbc:sub-protocol:database locator. El sub-protocol es especfico del driver JDBC y puede ser odbc, oracle, db2, etc., dependiendo del vendedor del driver real. El localizador de la base de datos es un indicador especfico del driver para especficar de forma nica la base de datos con la que una aplicacin quiere interactar. Dependiendo del tipo de driver, este localizador incluye un nombre de host, un puerto, y un nombre de sistema de base de datos. Cuando se presenta con una URL especfica, el DriverManager itera sobre la coleccin de drivers registrados hasta que uno de ellos reconoce la URL especficada. Si no se encuentra ningn driver adecuado, se lanza una SQLException. La siguiente lista presenta varios ejemplos especficos de URLs JDBC reales: jdbc:odbc:jdbc jdbc:oracle:thin:@persistentjava.com:1521:jdbc"; jdbc:db2:jdbc Muchos drivers, incluyendo el driver puente JDBC- ODBC, acepta parmetros adicionales al final de la URL como un nombre de usuario y una password. El mtodo para obtener una conexin a una base de datos, dando una URL JDBC especfica, es llamar a getConnection() sobre el objeto DriverManager. Este mtodo tiene varias formas: DriverManager.getConnection(url) ; DriverManager.getConnection(url, username, password) ; DriverManager.getConnection(url, dbproperties) ; Aqu url es un objeto String que es la URL JDBC, username y passwor d son objetos String que representan el nombre de usuario y la passw ord que la aplicacin JDBC debera usar para conectar con la fuente de datos; y dbproperties es un objeto Properties de Java que encapsula todos los parmetros (posiblemente incluyendo nombre de usuario y la password) que requiere un driver JDBC para hacer una conexin con xito. Ahora que tenemos el driver bsico en la mano, podemos examinar los tipos de drivers individuales con ms detalle:

Pgina 5 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Drivers del Tipo 1

Los drivers del tipo uno tienen algo en comn: todos usan el puente JDBC- ODBC, que est incluido como parte estndar d del JDK. Los drivers del tipo uno son diferentes al driver ODBC (Open DataBase Connectivity) adjunto al puente JDBC- ODBC. Para conectar con una fuente de datos diferente, simplemente tenemos que registrar (o unir efectivamente) una fuente de datos ODBC diferente, usando el Ad ministrador ODBC, al nombre de la fuente de datos apropiada. Como ODBC se ha estado utilizando desde hace bastante tiempo (ms que el lenguaje Java), los drivers ODBC son ubicuos. Esto hace de este tipo de drivers una buena eleccin para aprender cmo conectar programas Java a bases de datos. De hecho, incluso hay drivers ODBC que nos permiten asignar fuentes de datos ODBC a una aplicacin Microsoft Excel o ficheros de texto plano. Sin embargo, el nivel extra de indireccin, puede resultar en una prdida d e rendimiento ya que el JDBC es transferido dentro de ODBC, que luego es transferido en el protocolo especfico de la base de datos. Otro problema potencial de los drivers del tipo uno es su utilizacin en aplicaciones distribuidas. Como el propio puente no soporta comunicacin distribuida, la nica forma de que los drivers del tipo uno puedan trabajar a travs de la red es si el propio driver ODBC soporta interaccin remota. Para drivers ODBC sencillos, esta no es una opcin, y mientras que las grandes ba ses de datos tienen drivers ODBC que pueden trabajar de for ma remota, no pueden competir con el mejor rendimiento de los drivers JDBC puro Java.

Pgina 6 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Codificacin para Drivers del Tipo 1


El nombre de clase para el driver puente JDBC- ODBC es sun.jdbc.odbc.JdbcOdbcDriver y al URL JDBC toma la forma jdbc:odbc:dsn, donde dsn es el Data Source Name (nombre de la fuente de datos) usado para registrar la base de datos con el Administrador ADBC. Por ejemplo, si una base de datos se registra con una fuente de datos O DBC llamada jdbc; un nombre de usuario de java y una password de sun, se puede usar el siguiente fragmento de cdigo para establecer una conexin. Nota: En inters de la claridad y la brevedad, se ha eliminado del listado el chequeo y manejo de errores. Posteriores ejemplos, demostrarn la importancia de estos mecanismos (especficamente, la captura de errores encadenando sentencias SQLException). String url = "jdbc:odbc:jdbc" ; Connection con ; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ; } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: ") ; System.err.println(e.getMessage()) ; return ; } try { con = DriverManager.getConnection(url, "java", "sun"); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()); } finally { try{ con.close ; } catch(SQLException ex) { System.err.println(SQLException: " + ex.getMessage()) ; } }

Pgina 7 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Drivers del Tipo 2

Los drivers del tipo dos tambin son conocidos como drivers Java parciales, porque traducen directamente el API JDBC en un API especfico de la base de datos. La aplicacin cliente de base de datos (para el propstio de este tutorial, el host que est ejecutando la JVM) debe tener las libreras cliente apropiadas para la base de datos, que podran incluir cdigo binario instalado y posiblemente ejecutndose. Para una aplicacin distribuida, este re querimietno puede introducir problemas extra con las licencias, as como posibles pesadillas con los problemas de distribucin de cdigo. Por ejemplo, usar un modelo del tipo dos restringe a los desarrolladores a utilizar plataformas y sistemas operativos soportados por la librera cliente de la base de datos. Sin embargo, este modelo puede funcionar eficientemente, cuando la base cliente est fuertemente controlada.. Esto ocurre tpicamente en LANs corporativas. Un ejemplo de driver del tipo dos es el dri ver de aplicacin JDBC para DB2. El siguiente ejemplo demuestra cmo establecer una conexin usando un driver DB2: String url = "jdbc:db2:jdbc" ; try { Class.forName("COM.ibm.db2.jdbc.app.DB2Driver") ; } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: ") ; System.err.println(e.getMessage()) ; return ; } ... Observa la similitud que tiene este fragmento de cdigo con el del ejemplo 1. Esta es la principal caracterstica del modelo del tipo 2: la curva de aprendizaje para un programador que se mueve de un modelo a otro es prcticamente inexistente. Los dos ltimos tipos de drivers son drivers puro Java. El beneficio de los drivers puro Java es su fcil despliegue en entonos altamente distribuidos.

Pgina 8 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Drivers del Tipo 3

Los drivers del tipo tres son drivers puro Java que transforman el API JDBC en un protocolo independiente de la base de datos. El driver J DBC no comunica directamente con la base de datos; comunica con un servidor de capa media, que a su vez comunica con la base de datos. Este nivel extra de indireccin proporciona flexibilidad en que se puede acceder a diferentes bases de datos desde el mismo cdigo porque el servidor de la capa media oculta las especificidades a la aplicacin Java. Para cambiar a una base de datos diferente, slo necesitamos cambiar los parmetros en el ser vidor de la capa media. (Un punto a obser var: el formato de la base de datos a la que estamos accediendo debe ser sopor tado por el servidor de la capa media). El lado negativo de los drivers del tipo tres es que el nivel extra de indireccin puede perjudicar el rendimiento general del sistema. Por otro lado, si una aplicacin necesita interactar con una variedad de formatos de bases de datos, un driver del tipo tres en una aproximacin adecuada debido al hecho de que se usa el mismo driver JDBC sin impor tar la base de datos subyacente. Adems, como el servidor de la capa media se puede instalar sobre una plataforma hardware especfica, se pueden realizar cier tas optimizaciones para capitalizar los resultados perfilados.

Pgina 9 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Drivers del Tipo 4

Los drivers del tipo cuatro son drivers puro Java que se comunican directamente con la base de datos. Muchos programadores consideran ste el mejor tipo de driver, ya que normalmente proporciona un rendimiento ptimo y permite al desarrollador utilizar las funcionalidades especficas de la base de datos. Por supuesto este acoplamiento puede reducir la flexibilidad, especialmente si necesitamos cambiar la base de datos subyacente en una aplicacin. Este tipo de driver se usa frecuenteme nte en applets y otras aplicaciones altamente distribuidas. El siguiente fragmento de cdigo muestra cmo usar un driver DB2 del tipo cuatro: String url = "jdbc:db2://persistentjava.com:50000/jdbc" ; try { Class.forName("COM.ibm.db2.jdbc.net.DB2Driver") ; } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: ") ; System.err.println(e.getMessage()) ; return ; } ...

Pgina 10 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Un Ejemplo Completo de Driver del Tipo 4


El siguiente ejemplo muestra cmo usar un driver JDBC de un vendedor de terceras partes, en este caso Merant, para conectar con una base de datos DB2. DB2 UDB requiere informacin adicional, no estndard para establecer la conexin a la base de datos, que en este ejemplo estn aadidos a la URL JDBC como parmetros opcionales.
package com.persistentjava; import java.sql.*; public class ConnectMerantDB2 { static { try { Class.forName("com.merant.datadirect.jdbc.db2.DB2Driver").newInstance(); } catch (Exception e) { System.out.println(e); } } public static void main(String args[]) { String url = "jdbc:merant:db2://persistentjava.com:50000;" ; url += "DatabaseName=jdbc;CollectionId=DEFAULT;" ; url += "PackageName=JDBCPKG;CreateDefaultPackage=TRUE"; Connection con; System.out.println("Connecting"); try { con = DriverManager.getConnection(url, "java", "sun"); System.out.println("Connection Established"); con.close(); // In this example, the proper handling of SQLExceptions is // demonstrated as they can be potentially chained. } catch (SQLException e) { System.out.println("\nERROR:----- SQLException -----\n"); while (e != null) { System.out.println("Message: " + e.getMessage()); System.out.println("SQLState: " + e.getSQLState()); System.out.println("ErrorCode: " + e.getErrorCode()); e.printStackTrace(); e = e.getNextException(); } } } }

Pgina 11 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Transaciones con Bases de Datos


Transaciones Bsicas Uno concepto que causa problemas a los principiantes en el mundo del desarrollo de aplicaciones de base de datos es la idea de transaciones. Fundamentalmente, una transacin representa una unidad de trabajo lgica. Como la principal responsabilidad de una base de datos es preservar la informacin, necesita tener algo que le indique a un usuario que se debe salvar el estado actual del programa. De igual forma, cuando las cosas han ido mal, necesita una forma para indicar que una base de datos deberia ignorar el estado actual y volver a atrs, al estado del programa salvado anteriormente. En el idioma de las bases de datos, estas funciones se llaman entregar una transacin y deshacer una transacin, respectivamente. Para realizar estas tareas, el API JDBC incluye dos mtodos como parte del interface Connection. Dando un objeto Connection llamado con, el estado del programa se graba llamando a con.commit(), para volver al estado salvado anteriormente, con.rollback(). Estos dos mtodos pueden lanzar SQLExceptions si algo va mal cuando la base de datos realice realmente la operacin, por eso necesitamos envolverlos en bloques try ... catch. Ms sobre Transaciones En un entorno mono-usuairo, las transaciones son bastantes sencillas de entender -simplemente implican salvar o deshacer el estado de una aplicacin. Sin embargo, en modo multi-usuario, las transaciones son ms complejas. La demostracin clsica de una transacin multi-usuario es una cuenta bancaria donde una aplicacin est intentando hacer un cargo mientras otra aplicacin est intentando hacer un depsito en la misma cuenta. Si estas familiarizado con la programacin con currente (tambin conocida como programacin multithread), probablemente hayas visto este problema antes. El pr oblema fundamental es que a menos que las dos transaciones estn aisladas la una de la otra, una aplicacin podra interrumpir a la otra resulta ndo en un estado del programa incorrecto. En nuestra sencilla demostracin, esto podra significar una cuenta con un saldo errneo, algo que no es precisamente bueno para retener clientes. Pueden aparecer tres problemas comunes cuando tratamos con varios usuarios que acceden a los mismos datos: Lecturas sucias. Un lectura sucia ocurre cuando una aplicacin usa datos que han sido modificados por otra aplicacin, y esos datos estn en un estado sin entregar. La segunda aplicacin entonces solicita que los datos que fueron modificados sean desechos. Entonces los datos de la primera transacin estn corruptos o "sucios". Lecturas no-repet ibles. Una lectura no-repetible ocurre cuando una transacin obtiene datos, que posteriormente son alterados por una transacin separada, y la primera transacin re-lee los datos ahora alterados. As, la primera transacin hizo una lectura no-repetible. Lecturas fantasmas. Una lectura fantasma ocurre cuando una transacin adquiere datos mediante alguna consulta, otra transacin modifica algunos de los datos, y la transacin original recupera los datos una segunda vez. La primera transacin ahora tendr un conjunto de resultados diferentes, que podran contener datos fantasmas. Niveles de Transacin Para resolver los problemas asociados a mltiples threads solicitando los mismos datos, las transaciones estn aisladas unas de otras por bloqueos. La mayora de las bases de datos soportan diferentes tipos de bloqueo; por lo tanto, el API JDBC soporta diferentes tipos de transaciones, que son asignadas o determinadas por el objeto Connection. En el API JDBC tiene disponibles los siguientes niveles de transaciones: TRANSACTION_NONE indica que las transaciones no estn soportadas. TRANSACTION_READ_UNCOMMITTED indica que una transacin puede ver los cambios de otra transacin antes de ser entregada. As estn permitidas las lecturas sucias, las lecturas no repetibles, y las lecturas fantasmas.

Pgina 12 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

TRANSACTION_READ_COMMITTED indica que la lectura de datos no entregados, no est permitida. Este nivel todava permite que ocurran las lecturas no-repetibles y las lecturas fantasmas. TRANSACTION_REPEATABLE_READ indica que una transacin est garantizada que pueda releer el mismo dato sin fallar, pero las lecturas fantasmas todava pueden ocur rir. TRANSACTION_SERIALIZABLE es la transacin de ms alto nivel y evita que ocurran las lecturas sucias, las lecturas no-repetibles y las lecturas fantasmas. Podramos preguntarnos porqu todas las transaciones no operan en modo TRANSACT ION_SERIALIZABLE para garantizar el grado ms alto de integridad de datos. El problema es, de forma similar a los problemas implicados con el manejo de la programacin de mltiples threads, que cuanto ms sea el nivel de proteccin de transacin, ms alta ser la pr dida d e rendimiento. Dando un objeto Connection podemos seleccionar explcitamente el nivel de transacin, asumiendo que nuestra base de datos y nuestro driver JDBC soporten esta caracterstica: con.setTransactionLevel(TRANSACTION_SERIALIZABLE) ; Tambin podem os determinar el nivel de transacin actual: if(con.getTransactionLevel() == TRANSACTION_SERIALIZABLE) System.out.println("Highest Transaction Level in operation.") ; Lotes y Transaciones Por defecto, los drivers JDBC operan en lo que se llama modo autoentrega. En este modo, todos los comandos enviados a la base de datos operan en su propia transacin. Aunque esto puede ser til para los principiantes, implica una prdida de rendimiento porque las transaciones requieren una cier ta cantidad de sobrecar ga para configurar todo apropiadamente. Si queremos poder controlar explcitamente las entregas y los retrocesos (deshacer la transacin), necesitamos desactivar el modo autocommit: con.setAutoCommit(false) ; Tambin podemos determinar rpidamente el modo autocommit de un objeto Connection dado: if(con.getAutoCommit() == true) System.out.println("Auto Commit mode"); Muchas bases de datos soportan lotes, en los que se minimiza la sobrecarga de transaciones realizando mltiples operaciones update de la base de datos en una sla operacin, o lote. Las operaciones por lotes fueron introducidas en JDBC 2.0 y requieren que una transacin no est en modo autocommit. En el siguiente ejemplo tenemos una operacin por lotes, que asume que existe una Connection a una base de datos que tiene una sola tabla:
con.setAutoCommit(false) ; Statement stmt = connection.createStatement() ; stmt.addBatch("INSERT INTO people VALUES('Joe Jackson', 0.325, 25, 105) ; stmt.addBatch("INSERT INTO people VALUES('Jim Jackson', 0.349, 18, 99) ; stmt.addBatch("INSERT INTO people VALUES('Jack Jackson', 0.295, 15, 84) ; int[] updateCounts = stmt.executeBatch() ; con.commit() ;

Observa que el mtodo executeBatch() devuelve un array de cuentas actualizadas, una por cada operacin del lote. Un ltimo pr oblema con las operaciones por lotes es que pueden lanzar una nueva excepcin del tipo BatchUpdateException, lo que indica que fall al menos uno de los comandos del lote. Por eso, necesitamos aadir un manejador de excepciones correspondiente a nuestras operaciones por lotes. Control Fino de las Transaciones Empezando con el API JDBC 3.0, se aadi un nuevo elemento interface relacionado con las transaciones. Este interface presenta el concepto de savepoints. Los Savepoints proporcionan un marca dentro de una aplicacin de base de datos que puede usarse como un argumento cuando se llama al mtodo rollback. Como resultado, usando el API JDBC 3.0, ahora es posible seleccionar un savepoint antes de empezar una interaccin complicada con la base de datos y, dependiendo del resultado, entregar la transacin completa o deshacer hasta el savepoint y devolver la aplicacin a un punto conocido.

Pgina 13 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Para seleccionar un punto de salvado, creamos un objeto Savepoint desde el objeto Connection, como se ve aqu: Savepoint svpt = con.setSavepoint("Savepoint") ; Para deshacer hasta un Savepoint dado, simplemente le pasamos el objeto Savepoint deseado al mtodo rollback: con.rollback(svpt) ; Cuando no se necesitan ms, liberamos todos los objetos Savepoint para liberar los caros recursos de la base de datos para otros usuarios: con.releaseSavepoint(svpt) ; Observa que cuando entregamos o deshacemos una transacin, cualquier Savepoints creado podra conver tirse en invlido dependiendo del orden exacto y del tipo de operacin. Puedes ver la especificacin del API JDBC 3.0 o el manual de tu driver para ms informacin.

Pgina 14 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Fuentes de Datos
Fuentes de Datos Bsicas Uno de los principales benficios de usar el API JDBC es facilitar una programacin independiente de la base de datos, as la mayora de las aplicaciones JDBC pueden transferirse fcilmente a otra base de datos diferente. Sin embargo, todava hay dos tems que permacenen unidos a una base de datos particular, la clase JDBC Driver y la URL JDBC. Con la intr oduci n de las fuentes de datos en el API JDBC 2.0, se eliminaron incluso estas dependencias. Esencialmente un objeto DataSource representa una fuente de datos par ticular en una aplicacin Java. Adems de encapsular la informacin especfica de la base de datos y del driver JDBC en un slo objeto estndarizado, las fuentes de datos pueden actuar como una factora de Connection y proporcionar mtodos para seleccionar y obtener propiedades particulares que requiere el objeto DataSource para una operacin satisfactoria. Algunas propiedades estndar que podra requerir un objeto DataSource incluyen: databaseName serverName portNumber userName password Un beneficio adicional de usar una DataSource, que podras haber adivinado de la lista anterior, es que la informacin sensible relacionada con la seguridad como el nombre de usuario, la password, e incluso el ser vidor de la base de datos estn cdificados slo en un lugar, lo que puede hacer un administrador de sistemas. Mientras que la interaccin con un obj eto DataSource se puede hacer con una aplicacin grfica, es instructivo ver como trabajan realmente los ejemplos. Aunque los conceptos de un objeto DataSource son bastantes simples, para usarlo dentro de una aplicacin Java, un objeto DataSource es referenciado usando Java Naming and Directory Interface, o JNDI. Antes de saltar dentro del cdigo de ejemplo de DataSource, el siguiente punto presenta conceptos relevantes de JNDI que son necesarios para usar apropiadamente un objeto DataSource. Repaso Rpido de JNDI JNDI es un API Java que encapsula el concepto de servidores de nombres y directorios de la misma forma que JDBC encapsula los conceptos que hay detrs de la comunicacin con una base de datos. Aunque podra parecer confuso, es bastante sencillo -- todos lo usuarios de ordenadores usan servicios de nombres y directorios todos los das. Por ejempo, los discos duros trabajan con pistas y sectores, aunque un usuario slo se preocupa de nombres de ficheros y directorios. El sistema de ficheros maneja el ser vicio de nombrado que asocia un nombre de fichero dado con una localizacin especfica en el disco duro. Otro ejemplo es la Web, donde la mayora de los usuarios slo se preocupan del nombre de la Web site, como www.persistentjava.com, y no de la direccin IP subyacente. Sin embargo, la comunicacin TCP/IP se hace usando la direccin IP y no usando el nombre que leemos los humanos. La transformacin entre las dos representaciones la realiza el DNS, o Domain Name System. Aunque JDNI proporciona un API mplio y til por s mismo, nuestras necesidades son considerablemente simples. En breve, necesitamos conocer como hacer cuatro cosas: Crear un nombre y unirlo a un objeto Java. Buscar un nombre para recuperar un objeto Java. Borrar un nombre. Re-unir un nombre a nuevo objeto Java. En vez de proporcionar ejemplos JNDI imaginarios para las tareas anteriores, las siguientes secciones muestran ejemplos de estas tareas usando fuentes de datos JDBC. Todos estos ejemplos usan el proveedor de sistema de ficheros, que es una descar ga separada.

Pgina 15 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Registrar una Fuente de Datos Este ejemplo es una implementacin de un DataSource de tereceras partes de i-net soft ware para conectar con una base de datos MS SQL Server. Los comentarios en el cdigo marcan los puntos importantes de registr o (o inicialziacin) de una fuente de datos JDBC:
// We need to import the actual DataSource implementation import com.inet.tds.TdsDataSource; import java.util.Hashtable; import javax.naming.*; import javax.naming.directory.*; import java.sql.* ; import javax.sql.* ; public class InitializeJNDI { // First we define the relevant parameters for this datasource private String serverName = "persistentjava.com"; private int portNumber = 1433; private String login = "java"; private String password = "sun"; private String databaseName = "jdbc"; // This is the name we will assign to our datasource. Because we are // using the file system provider, our name follows the file system // naming rules. The JNDI reserved subcontext for JDBC applications is // jdbc, thus our name starts appropriately. private String filePath = "jdbc/pjtutorial"; public InitializeJNDI() { // To pass in the necessary parameters, we need to create and then // populate a Hashtable. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); try { // Create the initial context Context ctx = new InitialContext(env); // Here we create the actual DataSource and then set the relevant // parameters. TdsDataSource ds = new TdsDataSource(); ds.setServerName(serverName); ds.setPortNumber(portNumber); ds.setDatabaseName(databaseName); ds.setUser(login); ds.setPassword(password); ds.setDescription("JDBC DataSource Connection"); // Now we bind the DataSource object to the name we selected earlier. ctx.bind(filePath, ds); ctx.close(); // Generic Exception handler, in practice, this would be replaced by an // appropriate Exception handling hierarchy. } catch (Exception ex) { System.err.println("ERROR: " + ex.getMessage()); } } public static void main(String args[]) { new InitializeJNDI(); } }

Pgina 16 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Usar una Fuente de Datos El ejemplo anterior establece la relacin de unin entre el objeto DataSource y un nombre particular. La mgia de JNDI realmente la realiza el proveedor de servicio apropiado. En nuestro caso, usamos el proveedor del sistema de ficheros. Existen otras opciones, incluyendo LDAP (Lightweight Director y Access Protocol) o incluso un DNS . Para hacer realmente una conexin, necesitamos buscar el objeto DataSource usando el nombre al que fue unido. Obser va en el siguiente ejemplo que no hay ningn cdigo especfico de base de datos en ningn lugar:
import java.util.Hashtable ; import javax.naming.* ; import java.sql.* ; import javax.sql.* ; public class UtilizeJNDI { public UtilizeJNDI(){ try { // We need to set up the JNDI context so that we can properly interface // to the correct service provider, in this case the file system. Hashtable env = new Hashtable() ; env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory") ; Context ctx = new InitialContext(env) ; // Given the JNDI Context, we lookup the object and are returned // our DataSource DataSource ds = (DataSource)ctx.lookup("jdbc/pjtutorial") ; // Now we get a database connection and proceed to do our job. Connection con = ds.getConnection() ; System.out.println("Connection Established.") ; con.close(); // Note that proper error handling is not included here in order to keep // the example short. }catch(Exception e ) { e.printStackTrace(); } } public static void main (String args[]){ new UtilizeJNDI() ; } }

Pgina 17 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Re- Unir una Fuente de Datos Cuando queremos cambiar la base de datos particular o incluso el vendedor del DataSource JDBC con el que queremos que comunique nuestro cdigo, todo lo que necesitamos hacer es re-unir un nuevo DataSource al nombre original. En este ejemplo, usamos el mismo driver, pero cambiamos varios parmetros relevantes:
// We need to import the actual DataSource import com.inet.tds.TdsDataSource; import java.util.Hashtable; import javax.naming.*; import javax.naming.directory.*; import java.sql.* ; import javax.sql.* ; public class InitializeJNDI { // First we define the relevant parameters for this datasource private String serverName = "persistentjava.com"; private int portNumber = 1434; // Note the new port number private String login = "sun"; // New username/password combination private String password = "java"; private String databaseName = "ds"; // And even a new database name. // We keep the same name for our datasource, just bind a new DataSource // to it. private String filePath = "jdbc/pjtutorial"; public InitializeJNDI() { // Establish the proper JNDI Context Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); try { // Create the context Context ctx = new InitialContext(env); TdsDataSource ds = new TdsDataSource(); ds.setServerName(serverName); ds.setPortNumber(portNumber); ds.setDatabaseName(databaseName); ds.setUser(login); ds.setPassword(password); ds.setDescription("JDBC DataSource Connection, take two"); // Now we just call the rebind method with the new DataSource. ctx.rebind(filePath, ds); ctx.close(); // Replace this with real Exception handlers in production code. } catch (Exception ex) { System.err.println("ERROR: " + ex.getMessage()); } } public static void main(String args[]) { new InitializeJNDI(); } }

Pgina 18 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Borrar una Fuente de Datos Algunas veces, querremos borrar un nombre de DataSource para que no pueda volver a ser usado:
import java.util.Hashtable ; import javax.naming.* ; import java.sql.* ; import javax.sql.* ; public class DeleteJNDI { public DeleteJNDI() { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); try { Context ctx = new InitialContext(env); // unbinding the name object association effectively deletes the object. ctx.unbind("jdbc/pjtutorial") ; ctx.close() ; }catch (Exception ex) { System.err.println("ERROR: " + ex.getMessage()) ; } } public static void main (String args[]){ new DeleteJNDI() ; } }

Pgina 19 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Almacenes de Conexiones
Por qu necesitamos Almacenes de Conexiones Cuando usamos el DriverManager o el mtodo DataSource para obtener conexiones a bases de datos, cada solicitud para una nueva conexin implica una sobrecarga significa nte. Esto puede impactar en el rendimiento si la obtencin de nuevas conexiones ocurre con cier ta frecuencia, como podra ser el caso en un entor no de ser vidor Web. Para enfatizar por qu esto es cierto, sigamos un camino potencial de una solicitud de cone xin tpica con una base de datos: La aplicacin Java llama a getConnection(). El cdigo del vendedor JDBC (la implementacin del driver o del DataSource) solicita una conexin socket desde la JVM. La JVM necesita chequear los aspectos de seguridad de la llamada potencial. Por ejemplo, los applets slo se pueden comunicar con el servidor del que son originarios. Si lo aprueba, la llamada necesita pasar a travs del interface de red del host hasta la LAN corporativa. La llamada podra necesitar pasar a travs de un cortafuegos para alcanzar Internet o una WAN. La llamada alcanza eventualmente su subred de destino, donde podra necesitar pasar a travs de otro cortafuegos. La llamada alcanza el host de la base de datos. El servidor de base de datos procesa la solicitud de la nueva conexin. Se podra necesitar requerir la licencia del servidor para determinar si hay una licencia apropiada disponible. La base de datos inicializa una nueva conexin cliente, incluyendo toda las sobrecargas de memoria y sistema operativo. La llamada de retorno es enviada de vuelta al cliente JDBC (donde tiene que pasar por todos los cortafuegos y routers). La JVM recibe la llamada de retorno y crea un objeto Connection apropiado. La aplicacin Java recibe el objeto Connection. Claramente, solicitar un nuevo objeto Connection presenta una gran sobrecarga y muchos puntos de fallo potenciales. Para minimizar esta sobrecar ga, por qu no reutilizar conexiones a bases de datos en vez de borrarlas cuando hayamos terminado con ellas? Los diseadores de JDBC usaron este patrn de diseo popular cuando crearon el ConnectionPoolDataSource, que nos permite crear un almacen de conexiones a bases de datos que son reutilizadas en vez de eliminarlas cuando se cierran. Qu es una PooledConnection? Una PooledConnection es un tipo especial de conexin a base de datos que no se borra cuando se cierra, al contrario que los objetos Connection normales (el recolector de basura puede borrar las conexiones normales una vez que ya no son referenciadas). En en vez de esto, la PooledConnection es almacenada para una reutilizacin posterior, produciendo potencialmente una gran mejora del rendimiento. Trabajar con un almacen de conexiones a bases de datos es casi idntico a trabajar con objetos DataSource. Primero, en vez de crear un ejemplar de una clase que implemente el interface DataSource, creamos un ejemplar de una clase que implemente ConnectionPoolDataSource. Podemos usar JDNI para unir esta nueva fuente de datos a un nombe como antes. Para usar realmente un objeto de fuente de datos almacenado, llamamos a getPooledConnection() sobre el ConnectionPooledDataSource, que a su vez establece conexiones con la base de datos. Para crear un objeto Connection que ser usado, llamamos a getConnection() sobre el objeto PooledConnection en vez sobre los objetos DriverManager o DataSource como antes. Un beneficio adicional de esta aproximacin es que es mucho ms fcil manejar varios conjuntos de conexiones a bases de datos con un ConnectionPool porque l tiene cuidado automticamente. Esta automatizacin puede ser muy importante si nuestra licencias de cliente limitan el nmero de clientes que pueden conectarse simultneamente a la

Pgina 20 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

base de datos. El pr oceso completo es mucho ms sencillo de lo que suena, como muestran los siguientes ejemplos. Inicialiar un Almacen de Conexiones En este ejemplo, usamos una base de datos mSQL y el driver JDBC de cdigo abierto mSQL para crear un PooledDataSource. Todo el cdigo especfico de la base de datos est contenido en los procesos de inicializacin o de unin.
// First we import the relevant package import com.imaginary.sql.msql.* ; import java.util.Hashtable ; import javax.naming.* ; public class InitializeJNDI { private String serverName = "localhost" ; private String databaseName = "jdbc" ; private String userName = "java" ; private String password = "sun" ; // The appropriate JNDI subcontext for PooledDataSources is jdbcpool private String filePath = "jdbcPool/pjtutorial" ; private int portNumber = 1114 ; private int poolSize= 10 ; // We want to create a pool with 10 connections. public InitializeJNDI() { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); try { Context ctx = new InitialContext(env); // Create the PooledDataSource and set the relevant parameters. MsqlPooledDataSource ds = new MsqlPooledDataSource() ; ds.setServerName(serverName) ; ds.setPort(portNumber) ; ds.setDatabaseName(databaseName) ; ds.setUser(userName) ; ds.setPassword(password) ; ds.setMaxPoolSize(poolSize) ; // Bind the name and the DataSource object together ctx.bind(filePath, ds) ; ctx.close() ; } catch (Exception ex) { System.err.println("ERROR: " + ex.getMessage()) ; } } public static void main (String args[]){ new InitializeJNDI() ; } }

Pgina 21 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Usar un A lmacen de Conexiones Una vez que hemos inicializado el PooledDataSource, ahora podemos usarlo en aplicaciones Java para crear almacenes de conexiones a bases de datos. El siguiente ejemplo, es imaginario, pero efectivamente demuestra los puntos impor tantes. Un ejemplo ms realista podra ser un servlet, que configurara el almacen de conexiones en el mtodo init() del servlet y (re)utilizara la conexin por cada nueva solicitud del ser vicio:
import java.util.Hashtable ; import javax.naming.* ; import java.sql.* ; import javax.sql.* ; public class UtilizeJNDI { public UtilizeJNDI(){ try { Hashtable env = new Hashtable() ; env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory") ; Context ctx = new InitialContext(env) ; // Look up the DataSource given the appropriate name. ConnectionPoolDataSource ds = (ConnectionPoolDataSource)ctx.lookup("jdbcPool/pjtutorial") ; // A PooledConnection provides a special Connection which is not // destroyed when it is closed, but is instead placed back into the // pool of connections. PooledConnection pcon = ds.getPooledConnection() ; Connection con = pcon.getConnection() ; System.out.println("Connection Established") ; con.close(); } catch(Exception e ) { e.printStackTrace(); } } public static void main (String args[]){ new UtilizeJNDI() ; } }

Pgina 22 de 23

Manejar Conexiones a Bases de Datos con JDBC 3.0

Optimizar las Comunicaciones con Bases de Datos


Mtodos JDBC DataSource y Dr iver Esta seccin ecplia algunos de los mtodos menos conocidos del API JDBC que pueden ser utilizados para mejorar el rendimiento del sistema. Primero, todas las clases de fuentes de datos JDBC, el Driver , el DataSource, o el ConnectionPooledDataSource, proporcionan la habilidad de designar explcitamente un stream de salida del tipo caracter, setLogWriter(). Este stream acepta todos los logs y mensajes de seguimiento. Tambin hay un mtodo disponible para obtener el stream actual, getLogWriter(). Este puede ser extremadamente valioso cuando intentamos diagnosticar extraos bugs o para seguir el flujo de la aplicacin. Adems, todas las clases de fuentes de datos JDBc proporcionan un medio para asignar (setLoginTimeout()) u obtener (getLoginTimeout()) la cantidad de tiempo mxima que la clase de fuente de datos debera esperar a que se estalezca una conexin. Una clase interesante y rara vez utilizada es la clase DriverPr opertyInfo. Esta clase encapsula toda la informacin de propiedades que necesita un driver para establecer una conexin a una base de datos. DriverPropertyInfo puede usarse en una herramienta grfica para encontrar interactivamente los parmetros que un driver necesita y pedirle al usuario de la base de datos los valores correctos. Mtodos JDBC Connection Un objeto Connection o PooledConnection tambin tienen varios mtodos que se pueden utilizar para mejorar el rendimiento del sistema, tanto directa como indirectamente. Primero, asumiendo que el driver JDBC y la base de datos subyacente lo soportan, un objeto connection se puede configurar para ser de slo lectura, setReadOnly(). Esto puede mejorar el rendimiento del sistema para aplicaciones que no necesitan hacer cambios en la base de datos, ya que la base de datos no necesita preocuparse de almacenar nuevas pginas, mantener entradas de diario, o adquirir bloqueos de escritura sobre cualquiera de los datos. Otros mtodos que estn relacioandos de alguna forma son setAutoCommit() y setTransactionIsolation(). Como el descontrol de las transaciones puede causar grandes prdidas de rendimiento en la base de datos, estos mtodos mtodos y s us efecto deberan ser claramente entenedidos y cuidadosamente aplicados. Finalmente, un ltimo y frecuentemente olvidado mtodo es nativeSQL(), que taduce una consulta SQL dada en el lenguaje de consulta nativo de la base de datos subyacente. Examinando la versin nativa SQL de nuestra consulta, podriamos entender mejor cmo la base de datos est intepretando nuestra consulta, y entonces hacer las modificaciones adecuadas a nuestra aplicacin para mejorar el rendimiento general.

Pgina 23 de 23

S-ar putea să vă placă și