Многопоточность Spring JPA

Мы создаем продукт, поэтому с точки зрения производительности мне нужна помощь. Мы используем полный Spring (MVC, JPA, Security и т.д.)

У нас есть требование, согласно которому, скажем, для определенного потока может одновременно выполняться 100 бизнес-правил. Таких потоков и бизнес-правил может быть n количество.

Эти правила при выполнении фактически извлекают записи из таблиц в базе данных, они также будут содержать несколько ЛЕНИВЫХ ИНИЦИАЛИЗИРОВАННЫХ ОБЪЕКТОВ.

Я использовал Futures/Callables для многопоточности, но проблема в том, что он не может загрузить ЛЕНИВЫЕ переменные. Это дает исключение загрузки Hibernate, возможно, какая-то проблема в TRANSACTIONAL, которая не распределяется по разным потокам.

Подскажите, пожалуйста, есть ли другой подход?


person Ankur Singhal    schedule 09.11.2012    source источник
comment
несколько вещей. 1. трассировка после стека. 2. Для ленивой загрузки сессия должна быть открыта. 3. транзакции не могут охватывать несколько потоков, поскольку транзакционный контекст не может распространяться 4. использовать уровни изоляции транзакций. 5. По возможности используйте транзакции только для чтения   -  person Aravind Yarram    schedule 09.11.2012
comment
Посмотрите, поможет ли это. stackoverflow.com/questions/ 13070157/   -  person Sashi    schedule 09.11.2012
comment
@Pangea Я также думал, что есть проблема с транзакциями с потоками. Не могли бы вы рассказать об этом низкоуровневом дизайне, любом API, который мы можем использовать. Поскольку рабочий метод должен выполнять правила в разных потоках, и каждое правило состоит из n таблиц и столбцов.   -  person Ankur Singhal    schedule 09.11.2012
comment
@Sashi Даже если мы используем JTA, он не распространяет транс ctx по нескольким потокам, поскольку создание потока не находится в управлении контейнерами.   -  person Aravind Yarram    schedule 09.11.2012
comment
@ Пангея Ты прав. Возможно, придется использовать потоки, управляемые контейнером. В противном случае приложение должно иметь дело с распространением контекста транзакции.   -  person Sashi    schedule 09.11.2012
comment
@Sashi Даже потоки, управляемые контейнером, могут не работать. Это зависит от сервера приложений. Вам необходимо использовать компоненты, которые являются частью JEE Spec, чтобы обеспечить согласованную работу в контейнерах или переработать дизайн.   -  person Aravind Yarram    schedule 09.11.2012
comment
@Pangea На данный момент я не уверен, хочет ли спрашивающий решение, независимое от контейнера. Я согласен, что всегда хорошо быть независимым от контейнера. Некоторые серверы приложений реализуют стандартный API WorkManager — docs.oracle. com/cd/E11035_01/wls100/commonj/commonj.html   -  person Sashi    schedule 09.11.2012
comment
@Sashi Я использовал API workmanager, но, к сожалению, потоки управляются контейнером, но такие вещи, как транзакции, контексты безопасности, не распространяются.   -  person Aravind Yarram    schedule 09.11.2012
comment
@Pangea Вы правы, API не требует распространения. Это зависит от серверов приложений, решат ли они это сделать.   -  person Sashi    schedule 09.11.2012


Ответы (2)


Если вам действительно нужна асинхронная обработка, я предлагаю вам использовать способ, указанный в Java EE, т. е. использовать JMS/MDB.

В любом случае, поскольку кажется, что вы хотите, чтобы все данные были загружены в любом случае для вашей обработки. Итак, Eager извлекает все необходимые данные, а затем отправляет данные для параллельной обработки. Или пусть каждый из Tasks (Callables) извлекает данные, которые им нужны. По сути, я прошу вас изменить свой дизайн, чтобы границы транзакций не пересекали несколько потоков. Локализуйте границы в рамках одного потока.

person Aravind Yarram    schedule 09.11.2012

если какая-то Entity/Entity Collection лениво извлечена, и вы обращаетесь к ней в другом потоке, вы столкнетесь с исключением LazyInitialization, так как лениво загруженные сущности могут быть доступны только внутри транзакции, а транзакция не будет охватывать потоки.

Вы можете использовать шаблон DTO или, если вы делитесь объектом между потоками, вызовите его ленивый инициализированный геттер коллекций внутри транзакции, чтобы они извлекались внутри самой транзакции.

person Subin Sebastian    schedule 09.11.2012
comment
Также добавить ... после обработки нескольких вещей я хочу распределить работу в новый поток, который будет работать в фоновом режиме. (в основном аудит ведения журнала), основной поток вернет представление. Я также не хочу получать его в сущности, опять же проблема с производительностью. Теперь я должен передать свой объект новой транзакции, но у него будут ленивые объекты, которые я не хочу загружать в основной поток из-за проблем с производительностью. Итак, я пытаюсь вызвать геттеры или hibernate.intialize(), он выдает ленивое исключение, также, если я пытаюсь использовать Merge(), и я вызываю их hibernate.intialize, он выдает ленивое исключение. - person Ankur Singhal; 24.12.2012
comment
Кроме того, переданный объект может быть сохранен или даже нет... есть ли способ сохранить этот объект где-то из одного потока, а затем позже извлечь этот же объект и начать вызывать мои геттеры на этом - person Ankur Singhal; 24.12.2012
comment
Я написал сервис, в котором я получаю транзакцию. Теперь, после выполнения нескольких задач в службе, мне нужно вызвать метод запуска. Я написал ниже задачу. Но он не может перенести текущую транзакцию на другую службу. Следующая служба запускает собственную новую транзакцию вместо того, чтобы охватывать исходную. В результате мои прокси-объекты не могли быть загружены в новую транзакцию. - person Ankur Singhal; 26.02.2013