JDBC MySql práticas de pool de conexão para evitar o esgotado pool de conexão

Eu tenho um aplicativo da Web Java-JSF no GlassFish, no qual eu quero usar o pool de conexão. Portanto, criei um bean com escopo de application que serve com instâncias de Connection para outros beans:

 public class DatabaseBean { private DataSource myDataSource; public DatabaseBean() { try { Context ctx = new InitialContext(); ecwinsDataSource = (DataSource) ctx.lookup("jdbc/myDataSource"); } catch (NamingException ex) { ex.printStackTrace(); } } public Connection getConnection() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException { Connection connection = myDataSource.getConnection(); System.out.println("Succesfully connected: " + connection); //Sample: Succesfully connected: com.sun.gjc.spi.jdbc40.ConnectionHolder40@7fb213a5 return connection; } } 

Dessa forma, o pool de conexões é preenchido muito rapidamente; depois de algumas navegações através de visualizações ‘relacionadas ao database’, o aplicativo para com o seguinte:

RAR5117: Falha ao obter / criar conexão do pool de conexões [mysql_testPool]. Razão: As conexões em uso são iguais ao tamanho máximo do pool e ao tempo máximo de espera expirado. Não é possível alocar mais conexões. RAR5114: Erro ao alocar conexão: [Erro ao alocar uma conexão. Causa: as conexões em uso são iguais ao tamanho máximo do pool e ao tempo máximo de espera expirado. Não é possível alocar mais conexões.] Java.sql.SQLException: Erro ao alocar uma conexão. Causa: as conexões em uso são iguais ao tamanho máximo do pool e ao tempo máximo de espera expirado. Não é possível alocar mais conexões.

Estou fechando conexões e outros resources em todos os methods. O aplicativo executa tudo OK com conexões independentes.

O que estou fazendo de errado? Qualquer dica ou conselho seria apreciado.

A exceção indica um caso típico de código de aplicativo que vaza as conexões do database. Você precisa garantir que você adquira e feche todos eles ( Connection , Statement e ResultSet ) em um bloco try-with-resources no mesmo bloco de método de acordo com o idioma JDBC normal.

 public void create(Entity entity) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_CREATE); ) { statement.setSomeObject(1, entity.getSomeProperty()); // ... statement.executeUpdate(); } } 

Ou quando você não está no Java 7, em um bloco try-finally . Fechando-os finally irá garantir que eles também são fechados em caso de exceções.

 public void create(Entity entity) throws SQLException { Connection connection = null; PreparedStatement statement = null; try { connection = dataSource.getConnection(); statement = connection.prepareStatement(SQL_CREATE); statement.setSomeObject(1, entity.getSomeProperty()); // ... statement.executeUpdate(); } finally { if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {} if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {} } } 

Sim, você ainda precisa fechar as conexões, mesmo quando estiver usando o pool de conexões. É um erro comum entre os iniciantes que eles acham que ele irá lidar automaticamente com o fechamento. Isso não é verdade . O conjunto de conexões, por sua vez, retorna uma conexão empacotada que faz algo parecido com o seguinte no close ():

 public void close() throws SQLException { if (this.connection is still eligible for reuse) { do not close this.connection, but just return it to pool for reuse; } else { actually invoke this.connection.close(); } } 

Não fechá-los faria com que a conexão não fosse liberada de volta ao pool para reutilização e, assim, ela iria adquirir uma nova e outra vez até que o BD ficasse sem conexões, o que faria com que seu aplicativo travasse.

Veja também:

  • Com que frequência Connection, Statement e ResultSet devem ser fechados no JDBC?
  • É seguro usar uma instância java.sql.Connection estática em um sistema multithread?
  • Fechando Conexões JDBC no Conjunto

Se você precisar de pooling de conexões JDBC, por que não depende do que já está disponível? O pool de conexões AFAIK, JDBC é considerado mais ou menos um recurso padrão nesses servidores de aplicativos java, e IMO, você não deve construir isso sozinho se estiver interessado apenas em criar um aplicativo.

Aqui está um link que deve começar: http://weblogs.java.net/blog/2007/09/12/totd-9-using-jdbc-connection-pooljndi-name-glassfish-rails-application

O que você provavelmente deveria estar fazendo é descobrir como deixar seu aplicativo pegar uma conexão do pool usando o jndi.

    Intereting Posts