Как привязать транзакцию к нескольким потокам в режиме гибернации?

#hibernate #spring

#режим гибернации #spring

Вопрос:

Изначально код имел следующую структуру, и он работал отлично —

Начальный код:

 @Transactional
class foo
{
  void public work()
  {
      task1;
      task2;     
  }
}
  

Поскольку две задачи могли выполняться параллельно, мы провели рефакторинг, чтобы распределить их по двум потокам.
Написал две задачи в разных потоках, вызвал их параллельно и получаю следующую ошибку при вызове соответствующего DAO

Сеанс гибернации не привязан к потоку, а конфигурация не позволяет создавать здесь нетранзакционный сеанс

Поскольку сеанс гибернации привязан к текущему потоку, это становится проблемой с дочерними потоками.

Переработанный код:

 @Transactional
class foo
{
  void public work()
  {
      final Thread t1 = new Thread(new Job1());
      t1.start();

      final Thread t2 = new Thread(new Job2());
      t2.start();

      t1.join();
      t2.join(); 
  }

  class Job1
  {
     public void run()
     {
        task1;
     }   
  }

 class Job2
  {
     public void run()
     {
        task1;
     }   
  }
  

}

Ответ №1:

Даже если возможно разделить транзакцию, управляемую Spring, между несколькими потоками, это не очень хорошая идея, поскольку транзакции в режиме гибернации привязаны к Session s, а режим гибернации Session не потокобезопасен, поэтому вы не можете использовать одну и ту же транзакцию Session из нескольких потоков.

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