Procedure di pooling di connessioni JDBC MySql per evitare un pool di connessioni esaurito

Ho un’applicazione Web Java-JSF su GlassFish, in cui voglio utilizzare il pool di connessioni. Pertanto ho creato un bean con scope application che serve con le istanze di Connection per altri bean:

 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: [email protected] return connection; } } 

In questo modo il pool di connessioni viene riempito molto velocemente; dopo un po ‘di navigazione attraverso le viste’ db-related ‘, l’applicazione si ferma con il seguente:

RAR5117: Imansible ottenere / creare una connessione dal pool di connessioni [mysql_testPool]. Motivo: le connessioni in uso sono uguali a dimensioni massime del pool e tempo massimo di attesa scaduto. Imansible allocare più connessioni. RAR5114: Errore durante l’allocazione della connessione: [Errore nell’assegnazione di una connessione. Causa: le connessioni in uso sono pari alla dimensione massima del pool e al tempo di attesa massimo scaduto. Imansible allocare più connessioni.] Java.sql.SQLException: errore nell’assegnazione di una connessione. Causa: le connessioni in uso sono pari alla dimensione massima del pool e al tempo di attesa massimo scaduto. Imansible allocare più connessioni.

Sto chiudendo le connessioni e altre risorse in ogni metodo. L’applicazione funziona tutto OK con connessioni standalone.

Che cosa sto facendo di sbagliato? Qualsiasi consiglio o consiglio sarebbe apprezzato.

L’eccezione indica un caso tipico di codice dell’applicazione che perde le connessioni al database. È necessario assicurarsi di acquisire e chiudere tutti ( Connection , Statement e ResultSet ) in un blocco try-with-resources nello stesso blocco del metodo in base al normale linguaggio JDBC.

 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(); } } 

O quando non sei su Java 7, in un blocco try-finally . Chiudendoli finally garantirà che vengano chiusi anche in caso di eccezioni.

 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) {} } } 

Sì, è comunque necessario chiudere le connessioni da soli, anche quando si utilizza il pool di connessioni. È un errore comune tra i principianti che pensano che gestirà automaticamente la chiusura. Questo non è vero . Il pool di connessioni cioè restituisce una connessione incapsulata che fa qualcosa di simile a quanto segue in 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(); } } 

Se non si chiudono, la connessione non viene nuovamente rilasciata al pool per essere riutilizzata e quindi ne acquisirà una nuova ancora e ancora fino a quando il DB non esaurirà le connessioni che causeranno l’arresto anomalo dell’applicazione.

Guarda anche:

  • Con quale frequenza dovrebbero essere chiusi Connection, Statement e ResultSet in JDBC?
  • È sicuro utilizzare un’istanza java.sql.Connection statica in un sistema con multithreading?
  • Chiudere le connessioni JDBC nel pool

Se hai bisogno di un pool di connessioni JDBC, perché non ti affidi a ciò che è già disponibile? AFAIK, il pool di connessioni JDBC è considerato più o meno una funzionalità standard in questi server di applicazioni Java, e IMO, non dovresti volerlo build da solo se sei solo interessato a creare un’applicazione.

Ecco un link che dovrebbe iniziare: http://weblogs.java.net/blog/2007/09/12/totd-9-using-jdbc-connection-pooljndi-name-glassfish-rails-application

Quello che probabilmente dovresti fare è scoprire come permettere alla tua applicazione di prendere una connessione dal pool usando jndi.