"Too Many Connections" Java + Msql

Asked

Viewed 293 times

3

Hello, I have following problem, I have a function that searches the database and returns an object. I have a "for" function that calls this method almost 300 times, due to this amount of calls mysql is returning the following error.

Algo deu errado ao fazer uma ação envolvendo formulações. com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"

The code is below. I have no idea what I have to do to prevent this error from occurring, since I am closing Statement, Resultset and the connection in each query. Could you help me with that? Thank you.

 private Formulacao retornaFormulacaoDoItem(Item item) throws Exception {
    Connection cx = br.com.projeto.Conexao.Conexao.abrir();
    try {

        String comando = "SELECT * FROM Formulacao WHERE fk_item = ?";
        PreparedStatement ps = cx.prepareStatement(comando);
        ps.setInt(1, item.getIdItem());
        ResultSet rs = ps.executeQuery();
        Formulacao f = new Formulacao();
        ArrayList list = new ArrayList();
        NutrienteDAO nutri = new NutrienteDAO();
        int i = 0;
        while (rs.next()) {
            if (rs.getString("operador") != null) {
                list.add(rs.getString("operador"));
            } else if (rs.getString("fk_nutriente") != null) {
                list.add(rs.getString("fk_nutriente"));
            } else {
                list.add(nutri.retornaUmNutriente(rs.getInt("fk_nutriente")).getQuantidade());
            }
        }
        String[] re = new String[list.size()];
        for (int j = 0; j < list.size(); j++) {
            re[j] = list.get(j).toString();
        }
        f.setCalculo(re);
        ps.close();
        rs.close();
        return f;
    } catch (Exception e) {
        throw new Exception("Algo deu errado ao retornar os dados de formula do item" + e);
    } finally {
        cx.close();
    }
}

Connection class with seat.



import java.sql.Connection;
import java.sql.DriverManager;

/**
 *
 * @author jpsa
 */
public class Conexao {
    private static final String USUARIO = "root";
    private static final String SENHA = "123456";
    private static final String URL = "jdbc:mysql://localhost:3306/miner";
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    // Conectar ao banco
    public static Connection abrir() throws Exception {
        // Registrar o driver
        Class.forName(DRIVER);
        // Capturar a conexão
        Connection conn = DriverManager.getConnection(URL, USUARIO, SENHA);
        // Retorna a conexao aberta
        return conn;
    }
}


  • Add your connection class too, maybe the problem is in it.

  • @Diegof Pus.

  • Have you tried the ps and rs in the Finally block ?

  • Already checked if this function is not being called in parallel (multithreads)?

  • 3

    Are you making a connection per query? Normally you make the connection outside the loop, do what you have to do, and then close. Depending on the case, you can leave the connection open during the life of the application, but it depends on the scale on which it will be used.

  • Looking at this code I can’t tell for sure if you’re using connection pool. Apparently it is (otherwise even the 300 commands would be incredibly slow). The stop is as follows: in a pool, the connection is not immediately closed when it is abandoned - it is only closed after a time without use, so that your code does not close the connection when you give a close-up, but just return it to the pool. The next request comes very fast and ends up opening a new connection. Anyway, basically you’re doing it wrong.

  • You’re discovering why to manage the connection within the routine itself that reads and manipulates data is not a good practice. A good practice is to open the connection at the beginning of the main request, and use the same connection to execute all the commands of the request, in all the routines and subroutines that meet the request (unless you wanted some kind of parallelism).

  • 2

    In fact, it is not good practice or not (there is no reason for something to be called "good practice" or "bad practice" in programming, this is a stuck legend). In this case, it is really wrong, and the true reason is what Caffé explained after the good practice part :)

  • The connection was in the normal constructor method, I will only create this "Cx" connection to see if it closed the connection so, The Loop I speak of is not in the "return methodFormulacaoDoItem()" but in another class that calls this method in the loop .

  • This is what you said, @Bacco, a new legend, very poorly based, helping to reduce the quality of software produced by professionals who are still gaining experience. A pity... Fortunately I haven’t seen much ground for this new balelinha around.

  • 1

    @Bacco Just to not go too far, attend only to this specific example, is not wrong as you said. It’s just bad practice - after all it compiles, passes the automated test, and even works for a smaller amount of records, and could never go wrong. So it’s not necessarily wrong, but it’s necessarily bad practice, which can eventually turn out to be (as it turned out). Believing in the nonsense that "there is no good practice" is not a good practice :D

  • 2

    @Caffé is not a matter of faith, it is that in practice, everything that is called good practice or bad practice needs an explanation, so the term is just noise. And as it is a term that adds nothing of tangible information, it ends up being used absurdly more by those who have no way of explaining themselves. It turns into a crutch, and its continued use ends up reflecting a larger user problem. That my term "wrong" isn’t the best, but "bad practice" doesn’t say anything either. Better to say it’s "problematic for x, y, z," which is what you explained later, focusing on the reason for the problem,.

  • @Bacco No, my dear. Wrong. Not everything needs a good and understandable explanation immediately. Often we are not even prepared to understand the explanation in depth and heart yet, so it can be a big waste of time. If you were to expect to understand in depth all the right steps to produce good software before doing so, your first good software would come out at 60 years of career. A superficial explanation of output often advances the learning process, often until no explanation can be useful. That’s how it works in every field.

  • 2

    @Caffé is in charge of the readers to choose to follow their recommendations or mine, I think it is unnecessary to prolong the discussion here, I insist on my point with a reason that goes far beyond your person, enjoy who wants. But if you think your way is better for people, move on. My experience says no, but it also says that there is no point in arguing (until you are not exactly what I want to convince of anything, and I believe the reciprocal is true). So I am satisfied with what I said earlier.

  • Guys, about good practice let’s leave it to the machine man interface classes, and good college design practices, for now let’s focus on a database problem.

  • @And yet, my explanation was very superficial, and I quoted very superficially only one of the many problems that this bad practice can cause. Do you think that’s enough? Do you think I’ve gone beyond saying that it’s not "good practice"? Because I don’t think I was even close to being enough in my explanation (so much so that the AP didn’t understand, I can see by your next comment). So any superficial explanation serves? Just to avoid using the expression "good practice"? In this case, we have come to an agreement (except that I have nothing against this term).

  • @joaopaulosantosalmeida, let us chat. We are on time :D

  • @joaopaulosantosalmeida Please make a single Drivermanager.getConnection and use this same connection for the whole process, and tell us if the error goes away (and show the code, of course).

Show 13 more comments

1 answer

1


Hello,

Looking only at the method, it is correct. You make the query and close the ResultSet and PreparedStatement then. I would just put the closed() in the finally, along with the connection.

As the staff says in the comments.. The problem is you call it "300" times.. pq when we ask to do a closed on the objects, this closed is not immediate. It may take a few milliseconds, and in the middle, you keep bombing the base for more connections.

The solution would be to use the same connection, so try decreasing the calls to getConnection... do something like maintain a single connection and use this to make the 300 calls:

public static Connection abrir() throws Exception {
    Connection conn = null;
    if (conn != null) {
      Class.forName(DRIVER);
      conn = DriverManager.getConnection(URL, USUARIO, SENHA);
    }
    return conn;
}

A test I usually do is to monitor the existing connections at the base, this usually makes it very clear what happens.

It is wrong to leave it so.. but just for testing, comment on the cx.close(), Even if the connection is open all the time, you can test and confirm where the problem is.. then try to leave out of the for that step.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.