Безопасен ли поток сессии Hibernate? - PullRequest
18 голосов
/ 23 сентября 2010

Мне нужно знать, является ли сеанс Hibernate потокобезопасным или нет. Но очевидно, что к каждому потоку присоединяется новый сеанс для выполнения. Но мой вопрос: если в одном потоке я обновил какое-то значение сущности, будет ли это отражено в другом потоке во время выполнения того же времени?

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

например. текущий этап табл.

  ID      NAME      MARKS
------- --------- --------
  1       John       54

Я пытаюсь сделать следующее:

Student student = session.load(Student.class, 1);
student.setMarks(student.getMarks() + 1);
session.update(student);
session.close();

Когда я пытаюсь запустить приведенный выше код в цикле, скажем, 10, тогда значение «marks» в таблице «student» корректно обновляется, то есть значение обновляется до 64, что является правильным.

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

Ответы [ 5 ]

20 голосов
/ 23 сентября 2010

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

Даже с учетом этого ваше поведение может не соответствовать ожидаемому, поскольку транзакции вступают в игру. Вам нужно будет установить правильный уровень изоляции транзакции . См. Руководство по конфигурации , hibernate.connection.isolation свойство.

17 голосов
/ 23 сентября 2010

Сеанс Hibernate и потоки не смешиваются.

Не следует использовать сеанс из нескольких потоков одновременно, и я рекомендую использовать сеанс только из одного потока. Реализации сеансов БД даже не обязательно должны быть безопасными.

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

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

4 голосов
/ 09 августа 2015

Hibernate сессии не являются потокобезопасными.Используйте класс TheadLocal для создания сеансов для каждого потока: -

 private static ThreadLocal<Session> threadSafeSession = new ThreadLocal<Session>() {
    protected Session initialValue(){
    return sf.openSession();
      }
    };

В вашем методе получите сеанс для каждого потока как: -

Session session = threadSafeSession.get();
2 голосов
/ 11 марта 2017

Это зависит от того, как вы создаете сеанс.

Сессия может быть создана двумя способами в спящем режиме.

  1. getCurrentSession ()

Да. Он обеспечивает безопасность потоков, так как он гарантирует, что он создаст сеанс для каждого потока, если сеанс не существует. К этому прикреплена транзакция и автоматическое закрытие сессии.

  1. openSession ()

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

0 голосов
/ 02 сентября 2018

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

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

При этом необходимость в сеансе, безопасном для потоков, - это запах кода, указывающий на недостаток в дизайне уровня доступа к данным.

...