Совместное использование jdbc "Соединение" по потокам

У меня есть основной поток, который выполняется периодически. Он открывает соединение с помощью setAutoCommit (false) и передается как ссылка на несколько дочерних потоков для выполнения различных операций чтения/записи базы данных. В дочерних потоках выполняется достаточно большое количество операций. После того, как дочерние потоки завершили свои операции с db, основной поток совершает транзакцию с открытым соединением. Пожалуйста, обратите внимание, что я запускаю потоки внутри ExecutorService. Мой вопрос, целесообразно ли использовать соединение по потокам? Если "да", убедитесь, что приведенный ниже код правильно реализует его. Если "нет", каков другой способ выполнить транзакцию в многопоточном сценарии? комментарии/рекомендации/а-новая идея приветствуются. псевдокод...

Connection con = getPrimaryDatabaseConnection();
// let me decide whether to commit or rollback
con.setAutoCommit(false);

ExecutorService executorService = getExecutor();
// connection is sent as param to the class constructor/set-method
// the jobs uses the provided connection to do the db operation
Callable jobs[] = getJobs(con); 
List futures = new ArrayList();
// note: generics are not mentioned just to keep this simple
for(Callable job:jobs) {
    futures.add(executorService.submit(job));
}
executorService.shutdown();
// wait till the jobs complete
while (!executorService.isTerminated()) {
  ;
}

List result = ...;
for (Future future : futures) {
    try {
       results.add(future.get());
    } catch (InterruptedException e) {
      try {
        // a jobs has failed, we will rollback the transaction and throw exception
        connection.rollback();
        result  = null;
        throw SomeException();
      } catch(Exception e) {
       // exception
      } finally {
         try {
           connection.close();
         } catch(Exception e) {//nothing to do}
      }    
   }
}
// all the jobs completed successfully!
try {
  // some other checks
  connection.commit();
  return results;
} finally {
  try {
      connection.close();
  } catch(Exception e){//nothing to do}
}

Ответ 1

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

Я предпочел бы вам использовать Apache Connections Pool и предоставить отдельное подключение к каждому потоку.

Ответ 2

Вы можете создать прокси-класс, который поддерживает соединение JDBC и предоставляет синхронизированный доступ к нему. Нити никогда не должны напрямую обращаться к соединению.

В зависимости от использования и операций, которые вы предоставляете, вы можете использовать методы synchronized или блокировать объекты, если прокси-сервер должен быть заблокирован до тех пор, пока он не покинет определенное состояние.


Для тех, кто не знаком с шаблоном проектирования прокси. Здесь wiki article. Основная идея заключается в том, что экземпляр прокси скрывает другой объект, но предлагает ту же функциональность.

Ответ 3

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

Если у вас будут сотни сотрудников, вам необходимо предоставить синхронизируемый доступ к объектам Connection или использовать пул соединений, как предположили @mike и @NKukhar.