C3P0 вызывает закрытие потоков - PullRequest
0 голосов
/ 10 октября 2019

У меня странная проблема. У меня есть служебный класс, который содержит соединение и имеет функцию, которая готовит операторы. Затем операторы выполняются, закрываются, и все работает нормально.

Однако, когда я попытался добавить пул соединений с помощью ComboPooledDataSource, мои потоки закрылись. Я отладил его и вижу, что некоторые запросы выполняются успешно, но вдруг все закрывается, и только потоки c3p0 продолжают работать. Никаких исключений не выдается.

Я попытался установить для пула одно соединение, чтобы максимально точно имитировать рабочий код, но это также не удается. Если я устанавливаю элемент подключения для подключения из пула, все работает нормально, но если я пытаюсь использовать напрямую из пула, я получаю поведение, описанное выше.

Вот пример кода:

class DBUtilityClass
{
   private java.sql.Connection connection;
   private ComboPooledDataSource connectionPool;

   public void DBUtilityClass()
   {
      connect();
   }

   private void connect()
   {
      connectionPool = new ComboPooledDataSource();
      connectionPool.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver   
      connectionPool.setJdbcUrl(urlString.toString());
      connectionPool.setUser(user);
      connectionPool.setPassword(password);
      connectionPool.setAutoCommitOnClose(true);

      connectionPool.setInitialPoolSize(1);
      connectionPool.setMinPoolSize(1);
      connectionPool.setAcquireIncrement(1);
      connectionPool.setMaxPoolSize(1);


   }

   //Version 1 - this works if I set the connection in the constructor 
   //or if I connect the connection manually without using the pool
   public Connection getConnection()
   {
      connection.setAutoCommit(true);
      return connection;
   }

   //Version 2 - This fails
   public Connection getConnection()
   {
      Connection temp = connectionPool.getConnection();
      temp.setAutoCommit(true);
      return temp;
   }

   public PreparedStatement getPreparedStatement(String sql)
   {
      Connection temp = getConnection();
      return temp.prepareStatement(sql);
   }
}

1 Ответ

1 голос
/ 11 октября 2019

Функция public PreparedStatement getPreparedStatement(String sql) в вашем классе - это утечка Connection. Каждый раз, когда он вызывается, Connection извлекается из пула, но ссылка отбрасывается, поэтому она никогда не close() редактируется и не возвращается в пул.

(извините в нашемПоток комментариев выше занял у меня так много времени, чтобы увидеть это!)

Когда есть один общий Connection, это не проблема, одно Соединение остается проверенным. Но когда, как и в случае с пулом, вы извлекаете Connections точно в срок и не кэшируете их, вы должны быть уверены, что close(), когда закончите.

Убедитесь, что каждыйвызов getConnection() соответствует вызову close(). Самый простой способ сделать это -

  1. Не используйте здесь функцию getPreparedStatement (...) `, просто работайте с Соединениями
  2. Используйте try-with-resources
try( Connection conn = myDBUtilityInstance.getConnection ) {
  try( PreparedStatement ps = conn.prepareStatement( sql ) ) {
    // do work here
  }
}
...