Error MySQL "too many connections"

Buen día compañeros, traigo la siguiente inquietud espero me puedan orientar,
anteriormente para hacer una conexion a mysql lo hacia de la siguiente manera, creaba una clase conexion, compuesta de la siguiente manera

package Logica;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JOptionPane;

/**
 *
 * @author CARLOS
 */

public class conexion {
    public String db="basereserva";
    public String url="jdbc:mysql://localhost/" +db;
    public String user="root";
    public String pass="digito";

    public conexion() {
    }
   
    public Connection conectar(){
        Connection link=null;
       
        try {
            Class.forName("org.gjt.mm.mysql.Driver");
            link=DriverManager.getConnection(this.url, this.user, this.pass);
           
        } catch (ClassNotFoundException | SQLException e) {
            JOptionPane.showConfirmDialog(null, e);
           
        }
       
        return link;
    }
}

Pero esto me trajo con sigo un error "to many connections"
investigando un poco en Internet me encontré con el patrón de diseño Singleton, y me pareció la gran solución a mi problema con lo que al implementarla me quedo de la siguiente manera.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Josue
 */

public class Conexion {

    public static Conexion instance;//Singleton
    private Connection cn;

    private Conexion() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            cn = DriverManager.getConnection("jdbc:mysql://localhost/reminder", "root", "");
        } catch (SQLException | ClassNotFoundException ex) {
            Logger.getLogger(Conexion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
    public synchronized static Conexion comprobarEstado() {
        if (instance == null) {
            instance = new Conexion();
        }
        return instance;
    }

    public Connection getCn() {
        return cn;
    }
   
    public void cerrarConexion() {
        Conexion.instance = null;
    }
}

Adicional a esto inplemente un metodo finally en cada conexion que realizaba

private static final Conexion cn = Conexion.comprobarEstado();

    @Override
    public boolean create(ContactoDTO d) {
        PreparedStatement ps;
        try {
            ps = cn.getCn().prepareStatement(sqlInsert);

            ps.setString(1, d.getNombre());
            ps.setString(2, d.getApellidos());
            ps.setString(3, d.getTelefono());

            if (ps.executeUpdate() > 0) {
                return true;
            }
        } catch (SQLException e) {
            Logger.getLogger(ContactoDAO.class.getName()).log(Level.SEVERE, null, e);
        } finally {
            cn.cerrarConexion();
        }
        return false;
    }

Mi inquietud es, mi problema enrealidad se debia a esto o hay alguna otra razon por la cual pasaba lo dicho anterior

Comentarios

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 chicowed

Hice una prueba y el error

Hice una prueba y el error sigue apareciendo, :(

Some issue with MySQL

Imagen de chicowed

jaja

:(

Je, je. Perdón. Necesitas una

Je, je. Perdón. Necesitas una herramienta para monitorear las conexiones de tu MySQL. Por ejemplo, el MySQL Workbench.

También puedes ejecutar el siguiente comando:

show processlist

Manual de MySQL en español

http://downloads.mysql.com/docs/refman-5.0-es.a4.pdf

▲ Manual oficial de MySQL en español. No es la versión más reciente, pero no deja de ser muy útil.

Imagen de paranoid_android

Null no es cerrar en todos los drivers

Me parece que tienes un problema aquí.

    public Connection getCn() {
        return cn;
    }

public void cerrarConexion() {
        Conexion.instance = null;
    }

busca la documentación como se hace un close de la conexión

Imagen de chicowed

Ok revisare como cerrar la

Ok revisare como cerrar la Conexion de manera correcta

Esto es lo que marca el WorkBench lo que se me hace raro porque estoy haciendo pruebas y mi IP aparece muchas veces es la terminación .59

Seguire probando Gracias :)

Imagen de ezamudio

por eso...

Por esto es que ya no deberían estar inventando el hilo negro y mejor usar un componente que les maneje las conexiones como el JdbcTemplate de Spring. O al menos hacer algo similar por cuenta propia pero probarlo muy bien y sobre todo fijarse que siempre cierre las conexiones, y usar un DataSource para después permitir la posibilidad de usar un pool de conexiones.

Imagen de chicowed

De echo, mi idea es aprender

De echo, mi idea es aprender primero como funciona todo lo básico, para después aprender a utilizar frameworks,
y ya que hablamos del tema con cual framework me recomiendan para empezar.

Si quieres comenzar con JDBC

Si quieres comenzar con JDBC plano, aquí te dejo un ejemplito muy básico:

package com.grupochapa.tienda.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.grupochapa.tienda.exception.DAOException;

public class DAO {

   static {
      try {
         Class.forName("com.mysql.jdbc.Driver");
      } catch (Throwable t) {
         throw new ExceptionInInitializerError(t);
      }
   }

   protected Connection getConnection() throws SQLException {
      return DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "");
   }

   protected int getLastInsertId(Connection conn) throws DAOException {
      Statement stmt = null;
      ResultSet rs = null;
      try {
         stmt = conn.createStatement();
         rs = stmt.executeQuery("SELECT LAST_INSERT_ID() AS ID");
         rs.next();
         return rs.getInt("ID");
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (rs != null) {
            try {
               rs.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (stmt != null) {
            try {
               stmt.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

}

^^^ Esa es la forma más básica para obtener una conexión. Sin embargo, crear la conexión es un proceso costoso, por eso se recomienda utilizar un pool de conexiones.

package com.grupochapa.tienda.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.LinkedList;
import java.util.List;

import com.grupochapa.tienda.exception.DAOException;
import com.grupochapa.tienda.model.Producto;

public final class ProductoDAO extends DAO {

   private static final String FIND_ALL_SQL =
   "SELECT ID, CODIGO, NOMBRE, DESCRIPCION, COSTO, PRECIO, DESCONTINUADO FROM producto";
   private static final String FIND_BY_PK_SQL =
   "SELECT ID, CODIGO, NOMBRE, DESCRIPCION, COSTO, PRECIO, DESCONTINUADO FROM producto WHERE ID = ?";
   private static final String STORE_SQL =
   "INSERT INTO producto ( ID, CODIGO, NOMBRE, DESCRIPCION, COSTO, PRECIO, DESCONTINUADO ) VALUES ( ?, ?, ?, ?, ?, ?, ? )";
   private static final String UPDATE_SQL =
   "UPDATE producto SET CODIGO = ?, NOMBRE = ?, DESCRIPCION = ?, COSTO = ?, PRECIO = ?, DESCONTINUADO = ? WHERE ID = ?";
   private static final String DELETE_SQL =
   "DELETE FROM producto WHERE ID = ?";

   public List<Producto> findAll() throws DAOException {
      List<Producto> list = new LinkedList<Producto>();
      Connection conn = null;
      Statement stmt = null;
      ResultSet rs = null;
      try {
         conn = getConnection();
         stmt = conn.createStatement();
         rs = stmt.executeQuery(FIND_ALL_SQL);
         while (rs.next()) {
            list.add(fill(rs));
         }
         return list;
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (rs != null) {
            try {
               rs.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (stmt != null) {
            try {
               stmt.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

   public Producto findByPk(Integer id) throws DAOException {
      Connection conn = null;
      PreparedStatement ps = null;
      ResultSet rs = null;
      try {
         conn = getConnection();
         ps = conn.prepareStatement(FIND_BY_PK_SQL);
         ps.setInt(1, id); // PK, NOT NULL
         rs = ps.executeQuery();
         if (rs.next()) {
            return fill(rs);
         }
         return null;
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (rs != null) {
            try {
               rs.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (ps != null) {
            try {
               ps.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

   public int store(Producto vo) throws DAOException {
      Connection conn = null;
      PreparedStatement ps = null;
      try {
         conn = getConnection();
         ps = conn.prepareStatement(STORE_SQL);
         ps.setInt(1, vo.getId()); // PK, NOT NULL
         ps.setString(2, vo.getCodigo()); // NOT NULL
         ps.setString(3, vo.getNombre()); // NOT NULL
         if (vo.getDescripcion() != null) {
            ps.setString(4, vo.getDescripcion());
         } else {
            ps.setNull(4, Types.VARCHAR);
         }
         ps.setBigDecimal(5, vo.getCosto()); // NOT NULL
         ps.setBigDecimal(6, vo.getPrecio()); // NOT NULL
         if (vo.getDescontinuado() != null) {
            ps.setBoolean(7, vo.getDescontinuado());
         } else {
            ps.setNull(7, Types.BIT);
         }
         int rows = ps.executeUpdate();
         vo.setId(getLastInsertId(conn));
         return rows;
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (ps != null) {
            try {
               ps.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

   public int update(Producto vo) throws DAOException {
      Connection conn = null;
      PreparedStatement ps = null;
      try {
         conn = getConnection();
         ps = conn.prepareStatement(UPDATE_SQL);
         ps.setString(1, vo.getCodigo()); // NOT NULL
         ps.setString(2, vo.getNombre()); // NOT NULL
         if (vo.getDescripcion() != null) {
            ps.setString(3, vo.getDescripcion());
         } else {
            ps.setNull(3, Types.VARCHAR);
         }
         ps.setBigDecimal(4, vo.getCosto()); // NOT NULL
         ps.setBigDecimal(5, vo.getPrecio()); // NOT NULL
         if (vo.getDescontinuado() != null) {
            ps.setBoolean(6, vo.getDescontinuado());
         } else {
            ps.setNull(6, Types.BIT);
         }
         ps.setInt(7, vo.getId()); // PK, NOT NULL
         int rows = ps.executeUpdate();
         return rows;
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (ps != null) {
            try {
               ps.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

   public int delete(Integer id) throws DAOException {
      Connection conn = null;
      PreparedStatement ps = null;
      try {
         conn = getConnection();
         ps = conn.prepareStatement(DELETE_SQL);
         ps.setInt(1, id); // PK, NOT NULL
         int rows = ps.executeUpdate();
         return rows;
      } catch (SQLException e) {
         throw new DAOException(e);
      } finally {
         if (ps != null) {
            try {
               ps.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
         if (conn != null) {
            try {
               conn.close();
            } catch (SQLException ex) {
               // Ignore, log or throw
            }
         }
      }
   }

   protected Producto fill(ResultSet rs) throws SQLException {
      Producto vo = new Producto();
      vo.setId(rs.getInt("ID"));
      vo.setCodigo(rs.getString("CODIGO") != null ? rs.getString("CODIGO").trim() : "");
      vo.setNombre(rs.getString("NOMBRE") != null ? rs.getString("NOMBRE").trim() : "");
      vo.setDescripcion(rs.getString("DESCRIPCION") != null ? rs.getString("DESCRIPCION").trim() : "");
      vo.setCosto(rs.getBigDecimal("COSTO"));
      vo.setPrecio(rs.getBigDecimal("PRECIO"));
      vo.setDescontinuado(rs.getBoolean("DESCONTINUADO"));
      return vo;
   }

}

Como puedes darte cuenta, siempre asegúrate de cerrar la conexión. Y este pequeño ejemplo puede sufrir muchas mejores, como usar try-with-resources, hacerlo genérico, etc.