Vamos a ver un ejemplo de como crear un pool de conexiones con el servidor Apache Tomcat en una aplicación Java EE.
Usar un pool de conexiones es más eficiente que abrir una nueva conexión cada vez que sea necesario por lo tanto no hay motivo para no usar un pool de conexiones, vamos a ver como como configurar un pool de conexiones en Tomcat.
El primer paso es editar el archivo context.xml del Tomcat (/conf/context.xml) y añadir el datasource para después poder recuperarlo desde java con JNDI.
<Context>
<Resource name="jdbc/ConexionMySQL" auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="10" maxWait="5000"
username="usuarioBD" password="passwordBD" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/tuBaseDeDatos"/>
</Context>
Vamos a ver que significan los parámetros que hemos usado, si quieres ver todos los posibles aqui tienes la lista completa en ingles.
- maxActive: Indica el número máximo de conexiones que pueden estar abiertas al mismo tiempo.
- maxIdle: El numero máximo de conexiones inactivas que permanecerán abiertas, si el numero de conexiones inactivas es muy bajo puede darse el caso de que las conexiones se cierren porque se llega al máximo de conexiones inactivas y se vuelvan a abrir inmediatamente reduciendo la eficiencia ya que se perdería la ventaja del uso de pool de conexiones en cuanto a que no hay que abrir una conexión cada vez que es necesario.
- maxWait: Es el tiempo máximo (en ms) que se esperará a que haya una conexión disponible (inactiva), si se supera este tiempo se lanza una excepción.
- username: Usuario de la base de datos.
- password: Password para el usuario introducido en username.
- driverClassName: Nombre del driver JDBC para conectar con la base de datos.
- url: URL de la base de datos a la que nos queremos conectar.
Si ${catalina.base} es distinto de ${catalina.home} el archivo que tienes que editar es ${catalina.base}/conf/context.xml, si por ejemplo usas NetBeans te encontraras en este caso (Puedes ver la ruta a la que apunta catalin.base en las propiedades del Tomcat haciendo click derecho sobre el servidor. ) y el archivo context.xml no existe por lo que lo tendrás que crear o copiar de la carpeta de instalación del Tomcat.
Ahora hay que añadir el recurso creado en el descriptor de despliegue de nuestra aplicación (WEB-INF/web.xml).
<resource-ref>
<description>Pool conexiones MySQL</description>
<res-ref-name>jdbc/ConexionMySQL</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Con estos pasos ya tenemos el pool listo para poder ser usado en nuestras aplicación ya solo queda incluir la librería del driver JDBC correspondiente en ${catalina.home}/lib/ o incluirla en la aplicación, en la documentación pone que hay que incluirla en la carpeta del Tomcat pero si la pones en la aplicación también funciona.
Y para terminar un ejemplo de uso del pool de conexiones usado, que no tiene demasiado que explicar pues la diferencia de usar el pool o no esta en que si no se hace la conexión se obtiene desde DriverManager y en este caso se hace desde el DataSource que obtenemos haciendo lookup sobre InitialContext pasándole el nombre del DataSource que hemos creado, precedido de «java:/comp/env/». Y una vez obtenida la conexión todo es igual pero hay que asegurarse de cerrar el ResulSet y el Statement porque aunque se «cierre» la conexión en realidad lo que ocurre es que se devuelve al pool por lo que hay que cerrarlos manualmente porque el ResulSet y el Statement se cierran automáticamente si se cierra la conexión pero en un pool las conexiones no se cierran (bueno, si el numero de conexiones inactivas es mayor que el indicado en maxIdle si se cierran). Y finalmente devolver la conexión al pool para que pueda ser reutilizada.
Context initContext;
Connection cn = null;
Statement st = null;
ResultSet rs = null;
try {
initContext = new InitialContext();
DataSource ds = (DataSource) initContext.lookup("java:/comp/env/jdbc/ConexionMySQL");
cn = ds.getConnection();
String sqlBusqueda = "SELECT nombre, apellido FROM clientes";
st = cn.createStatement();
rs = st.executeQuery(sqlBusqueda);
while (rs.next()) {
out.println("Nombre: " + rs.getString("nombre") + "
");
out.println("Apellido: " + rs.getString("apellido") + "
");
}
} catch (SQLException ex) {
log.error("Error (" + ex.getErrorCode() + "): " + ex.getMessage());
} catch (NamingException ex) {
log.error("Error al intentar obtener el DataSource: " + ex.getMessage());
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
log.error("Error (" + ex.getErrorCode() + "): " + ex.getMessage());
}
}
if (st != null) {
try {
st.close();
} catch (SQLException ex) {
log.error("Error (" + ex.getErrorCode() + "): " + ex.getMessage());
}
}
if (cn != null) {
try {
cn.close();
} catch (SQLException ex) {
log.error("Error (" + ex.getErrorCode() + "): " + ex.getMessage());
}
}
}
También se puede usar el pool de conexiones desde una pagina JSP si pasas del MVC.
<sql:query var="clientes" dataSource="jdbc/ConexionMySQL">
SELECT nombre, apellido FROM clientes
</sql:query>
<c:forEach var="cliente" items="${clientes.rows}">
Nombre: ${cliente.cantidad} <br />
Apellido: ${cliente.tipo} <br />
</c:forEach>
Aquí puedes descargar el proyecto de ejemplo (el archivo context.xml esta incluido en el rar).
Iván,
Muy bueno tu tutorial, esta muy claro!. Me sirve muchisimo, justamente necesito implementar un pool, soy nuevo en Java.
Tengo una duda, en qué momento se instancia el POOL?.
Se instancia cuando se realiza una petición desde el browser?, eso implicaría n peticiones n POOLs creados, y cada POOL puede tener seteado su propia cantidad de conexiones. Si es de esa manera, finalmente, por toda la aplicación tendríamos (n conexiones * n peticiones)?.
O el POOL es un objeto que ya lo tengo disponible/instanciado simplemente por declararlo en el Context.xml del Tomcat?.
Espero que respondas, mi email: jmsalinas88@hotmail.com
Nuevamente, muchas gracias por el tutorial, esta perfecto!.
Juan M. Salinas
La idea del pool de conexiones es tener unas cuantas conexiones creadas y disponibles para cuando sea necesario usarlas y una vez que la petición termina la conexion se devuelve al pool (pero no se cierra) para poder atender a otras peticiones con un mayor rendimiento que creando una conexión para cada petición.
Vamos que el pool se crea cuando arrancas el Tomcat y luego tu lo puedes usar en todas las aplicaciones que quieras y en los metodos que necesites obteniendo el DataSource donde necesites usar la conexión.
muy buen tutorial pero me sale este error
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class » for connect URL ‘null’
a ver que me puedes decir y muchas gracias
Debes colocar el driver de mysql en la carpeta lib del tomcat
Lo primero gracias, tu explicación es muy clara.
Pero me ha surgido una pregunta, se puedes conectar dos pools de comunicaciones en un servidor Tomcat?. Me explico, me gustaría montar dos diferentes webapps (Java EE) en un mismo servidor tomcat, pero cada una tiene su propia BBDD. Sé que para que tomcat acepte otro servicio sólo hay que configurarlo en server.xml, pero el resource del context, ¿cómo se haría para tener dos diferentes?
Si son 2 aplicaciones distintas lo único que van a tener en común será la configuración del tomcat, por lo tanto lo único que tienes que hacer es llamar al resource correspondiente en cada aplicación y hacer el lookup de ese pool