Pool de conexiones - Java

Hola todos les agradezco que estén leyendo este foro necesito que me den una mano para adaptar una conexión que tengo a un Pool de conexiones con MySql estuve leyendo pero la verdad es que soy nuevo en este tema. La necesidad surge por la lentitud en el programa al mostrar los datos, tengo la sgte conexión:

//Con_BD.java
public class Con_BD {
   
    public static Connection getConnection() {
       
        Connection cn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://direccion:3306/basedatos";//direccion:puerto/bd
            String user = "user";//usuario
            String password = "123456";//contraseña
            cn= DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            System.out.println("Error no se puede cargar el driver:" + e.getMessage());
        } catch (SQLException e) {
            System.out.println("Error no se establecer la conexion:" + e.getMessage());
        }
        return cn;
    }
}

Tengo otro archivo llamado Personal.java que contiene los get y set de mis campos

//trozo de Personal.java
public class Personal {
    private String uname;

    public String getuname(){
        return uname;
    }
    public void setuname(String uname){
        this.uname=uname;
    }
}

Bueno luego utilizo esta conexión en mis archivos para hacer las consultas etc...

//Trozo de BD_Personal.java
public static Personal buscarPersonalUNCompCodigo(int codigo) throws SQLException {
        Connection cnn = Con_BD.getConnection();
        PreparedStatement ps = null;
        Personal ms = null;
        ps = cnn.prepareStatement("select uname from personal where id_personal=?");
        ps.setInt(1, codigo);
        ResultSet rs = ps.executeQuery();
        if (rs.next()) {
            ms = new Personal() {
            };
           
            ms.setuname(rs.getString("uname"));
        }
        cnn.close();
        ps.close();
        return ms;
    }

Aquí utilizo Con_BD.getConnection() y esto es lo que necesitaría con el Pool ya que todos mis archivos los tengo así.

Bueno este ya es casi un aporte espero su ayuda ya luego are unos aportes como alternativas a las que te da Java como que opinan del código. Saludos y gracias de antemano

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de neko069

Pool

No dices qué pool estás usando, pero igual échale una revisada a BoneCP y C3p0.
Y es tu método de conexión lo que vas a tener que cambiar en todo caso =)

Imagen de Kewin

No se exactamente...

Hola neko069 para ser sincero no se exactamente que es pero uso commons-dbcp-1.4, commons-logging-1.0.4, log4j-1.2.15 en un ejemplo que encontré

Imagen de ezamudio

errores

Hay un montón de problemas con ese código.

Aunque no caches la excepción en el método que hace la búsqueda, deberías de tener de todas formas un try-finally para cerrar la conexión si es que la pudiste obtener:

Connection c = null;
PreparedStatement ps = null;
try {
  c = obtenerConexion();
  //usar la conexion
  ps = c.prepareStatement();
  //etc
  return ms;
} finally {
  if (ps != null) ps.close();
  if (c != null) c.close();
}

Me gustaría saber cómo determinaste que la lentitud en la aplicación se debe a la manera en que obtienes la conexión.

El pool de conexiones no es otra cosa que un objeto que vas a crear y configurar con los parámetros del número de conexiones que debe manejar, el tiempo de vida de las mismas en periodos de inactividad, queries para validar las nuevas, etc. Eso lo tienes que hacer una sola vez, así como realmente lo de Class.forName lo tienes que hacer una sola vez, no es necesario que lo hagas en cada invocación.

Cuando dices "soy muy nuevo en este tema", qué es "este tema"? Pools de conexiones? Aplicaciones que usan una base de datos relacional? Java? Programación?

Imagen de Kewin

Ok...

Hola ezamudio claro si utilizo el finally en el pool que encontré:

finally {
                        try {
                                if ( rs != null)
                                        rs.close( );
                                if ( stm != null)
                                        stm.close( );
                                 getDbPool().returnConnection(con);
                               
                        } catch ( SQLException exception) {
                               
                                throw new Exception( exception.getMessage( ), exception
                                                .getCause( ));
                        }
                }

Bueno de manera local no me trae problemas esta conexión por consulta demora de 0.6 a 0.4 seg osea esta bien y esto "Eso lo tienes que hacer una sola vez, así como realmente lo de Class.forName lo tienes que hacer una sola vez, no es necesario que lo hagas en cada invocación." a que te refieres exactamente?. En Java y BD con ello el tema del Pool en java tengo ya algún tiempo y bueno en otros lenguajes también.

Imagen de ezamudio

syntax error

No entendí mucho de lo que escribiste. Tampoco entiendo cómo es que hay un "finally" hasta afuera y luego unos try's adentro. No entiendo por qué cachas la SQLException para arrojar una Exception con el mismo mensaje y causa de la SQLException, se me ocurren pocas cosas peores que podrías hacer. Mejor no caches nada y deja que se arroje la excepción.

En tu código original tienes un Class.forName("blabla") para cargar el driver de jdbc. Eso es necesario hacerlo una sola vez en la vida de la aplicación y tú lo haces cada vez que alguien pide una conexión. No sé cómo obtienes la conexión ahora con el pool pero 0.4 me parece demasiado, pero bueno tampoco tengo idea de cómo estás tomando esos tiempos.

Imagen de Kewin

Me explico un poco mas

public void getLibro(String isbn) throws Exception {
                Connection con= getDbPool().getConnection();           
                String query = "select id_producto from producto";             
                Statement stm = null;
                ResultSet rs = null;
                try {
                        stm = con.createStatement();
                        rs = stm.executeQuery(query);
                        while(rs.next()){
                                System.out.println("ID:"+rs.getString("id_producto")); 
                        }
                } catch ( SQLException exception) {
                        throw new Exception( exception.getMessage( ), exception.getCause( ));
                } finally {
                        try {
                                if ( rs != null)
                                        rs.close( );
                                if ( stm != null)
                                        stm.close( );
                                 getDbPool().returnConnection(con);
                               
                        } catch ( SQLException exception) {
                               
                                throw new Exception( exception.getMessage( ), exception
                                                .getCause( ));
                        }
                }
        }

En el anterior solo puse el finally. Si en necesario que les pase el pool de ejemplo lo hago.

Haber me explico un poco mas el código que copie al iniciar el foro es lo que uso sin el Pool es el código que me demora 0.4 a 0.6 seg haciendo un limit 0,10 para q no me cargue los 100 o mas registros que tenga este código lo uso de manera local y si lo conecto a una bd en un servidor usando internet me demora algo de 12 seg por los 10 registros esto es exagerado. Probé un Pool que encontré y con mas de 400 registros me va en 2 segundos a lo mucho pero la consulta es de tipo select * from tabla osea creo que de alguna este tiempo va bien sin optimizar.
Ezamudio estas son las recomendaciones que necesito se que saben mucho aquí por eso recurro a ustedes para que me orienten y poder hacer las cosas lo mejor que se pueda.

Imagen de DianitaYPP

Estoy usando dbcp pero al correr el programa no me consulta

Buenas,
Soy nueva en el foro, pero les pido que me ayuden!!, Hace unos añitos ya realice una aplicación pero resulta que comenzo a fallar en el número de conexiones, así que decidí usar el pool de conexiones dbcp, la clase compila bien pero al momento de correr mi programa en el tomcat 6, estoy programando en jsp,no me genera error pero no me muestra la consulta, yo tenía una clase de conexión anterior que no usaba pool pero me funcionaba y consultaba correctamente, no se que este haciendo mal, esta es la clase:

package prueba;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import javax.naming.InitialContext;

/**
* Ejemplo simple de uso de BasicDataSource.
*
* @author Chuidiang
*/
public class BaseDatos{

/**
* @param args
*/
protected ResultSet rs;

/** Pool de conexiones */
private DataSource dataSource;

/**
* Inicializa el pool de conexiones BasicDataSource y realiza una insercion
* y una consulta
*/
public BaseDatos() {

inicializaDataSource();

}

/**
* Inicializacion de BasicDataSource
*/
private void inicializaDataSource() {

BasicDataSource basicDataSource = new BasicDataSource();

basicDataSource.setDriverClassName("org.postgresql.Driver");
basicDataSource.setUsername("postgres");
basicDataSource.setPassword("54");
basicDataSource.setUrl("jdbc:postgresql://localhost:5432/prueba");

// Opcional. Sentencia SQL que le puede servir a BasicDataSource
// para comprobar que la conexion es correcta.
System.out.println("Validar conexion");
basicDataSource.setValidationQuery("select 1");

dataSource = basicDataSource;
}

/**
* Realiza una insercion, pidiendo una conexion al dataSource y cerrandola
* inmediatamente despues, para liberarla.
*/
public boolean insertar(String inser) throws Exception {
System.out.println("Sentencia que llega Insertar: "+inser);
Connection conexion = null;
boolean s=false;

try {
// BasicDataSource nos reserva una conexion y nos la devuelve.
System.out.println("Entro a insertar, antes del getConnection");
conexion = dataSource.getConnection();
System.out.println("Conexión del Método Insertar"+conexion);

if(conexion!=null){
// La insercion.
Statement ps = conexion.createStatement();
ps.executeUpdate(inser);
s=true;

}
else{
s=false;
}

} catch (SQLException e) {
e.printStackTrace();
} finally {
liberaConexion(conexion);

}

return s;
}

/**
* Cierra la conexion. Al provenir de BasicDataSource, en realidad no se
* esta cerrando. La llamada a close() le indica al BasicDataSource que
* hemos terminado con dicha conexion y que puede asignarsela a otro que la
* pida.
*
* @param conexion
*/
private void liberaConexion(Connection conexion) {
try {
if (null != conexion) {
// En realidad no cierra, solo libera la conexion.
conexion.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

/**
* Realiza una consulta a la base de datos y muestra los resultados en
* pantalla.
*/
public ResultSet consultar(String consu)throws Exception{
System.out.println("Sentencia que llega Consultar: "+consu);
Connection conexion = null;
try {
System.out.println("Entro a consultar, antes del getConnection");
conexion = dataSource.getConnection();
System.out.println("Conexión del Método Consultar"+conexion);
Statement sentencia = conexion.createStatement();
rs= sentencia.executeQuery(consu);

} catch (SQLException e) {
e.printStackTrace();
} finally {
// En el finally, para asegurar que se ejecuta, se cierra la
// conexion.
liberaConexion(conexion);
}
System.out.println("ResultSet"+rs);
return rs;
}

public boolean validar(String consul)throws Exception{

boolean sesion=false;
Connection conexion = null;
try {
System.out.println("Entro a validar, antes del getConnection");
conexion = dataSource.getConnection();
System.out.println("Conexión del Método Validar"+conexion);
Statement sentencia = conexion.createStatement();
rs= sentencia.executeQuery(consul);

if(rs.next())sesion=true;

} catch (SQLException e) {
e.printStackTrace();
} finally {
// En el finally, para asegurar que se ejecuta, se cierra la
// conexion.
liberaConexion(conexion);
}
return sesion;

}

}

Gracias!

Imagen de Kewin

Código Pool...

Hola DianitaYPP como estas llamando tu consulta por que aquí no veo nada...