Подтвердить что ты не робот

JAVA: объект EntityManager в многопоточной среде

если у меня есть несколько потоков, каждый использует инжектор для получения объекта EntityManager, каждый из которых использует объект em для выбора списка других объектов класса. Готов к использованию в цикле for.

Если поток заканчивается первым и вызывает clear(), это повлияет на другие потоки? Как и цикл for будет иметь исключение?

Как насчет close()?

Если ответ "Это зависит", что (метод определения класса?) и где (java code? annotation? xml?) следует посмотреть, как это зависит?

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

Спасибо.

4b9b3361

Ответ 1

Здесь находится полная работа thread-safe Entity Manager Helper.

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EntityManagerHelper {

    private static final EntityManagerFactory emf;
    private static final ThreadLocal<EntityManager> threadLocal;

    static {
        emf = Persistence.createEntityManagerFactory("Persistent_Name");
        threadLocal = new ThreadLocal<EntityManager>();
    }

    public static EntityManager getEntityManager() {
        EntityManager em = threadLocal.get();

        if (em == null) {
            em = emf.createEntityManager();
            // set your flush mode here
            threadLocal.set(em);
        }
        return em;
    }

    public static void closeEntityManager() {
        EntityManager em = threadLocal.get();
        if (em != null) {
            em.close();
            threadLocal.set(null);
        }
    }

    public static void closeEntityManagerFactory() {
        emf.close();
    }

    public static void beginTransaction() {
        getEntityManager().getTransaction().begin();
    }

    public static void rollback() {
        getEntityManager().getTransaction().rollback();
    }

    public static void commit() {
        getEntityManager().getTransaction().commit();
    }
}

Ответ 2

Менеджеры сущностей не являются потокобезопасными (источник учебник по Java EE 6) и не могут быть разделены между потоками. Каждый поток должен использовать свой собственный менеджер сущностей, иначе будут происходить плохие вещи, независимо от вызовов clear() или close().

Но если инжектор вводит каждый поток своим собственным менеджером сущностей, тогда все должно быть ОК.

Spring и, возможно, другие рамки DI будут внедрять прокси-сервер ThreadLocal для реального менеджера объектов в ваш beans. Вызовы, которые каждый поток делает, будут прокси-сервером для реального потока-локального экземпляра диспетчера сущностей - вот как все может работать, хотя может показаться, что диспетчер сущностей совместно используется несколькими потоками.

Более подробная информация о том, как вводится ваш менеджер объектов, поможет (Spring и т.д.)

Ответ 3

Существует два типа управления EntityManager: управление контейнером и управление приложениями. Для управления приложениями предпочтительный метод получения EntityManager осуществляется через EntityManagerFactory. Учебник Java EE гласит следующее:

Менеджеры, управляемые контейнером

С объектом, управляемым контейнером менеджер, контекст постоянства экземпляров EntityManager автоматически распространяемый контейнером во все приложения компоненты, которые используют экземпляр EntityManager в одной Java-среде Transaction API (JTA).

Операции JTA обычно включают вызовы между компонентами приложения. Для завершения транзакции JTA эти компоненты обычно нуждаются в доступе к единый контекст сохранения. Это происходит, когда EntityManager вводится в компоненты приложения посредством javax.persistence.PersistenceContext аннотация. Настойчивость контекст автоматически распространяется с текущей транзакцией JTA, и ссылки EntityManager, которые сопоставляются с одинаковой устойчивостью блок обеспечивает доступ к контексту персистентности в пределах этого сделка. Путем автоматического распространения контекста персистентности, прикладным компонентам не нужно передавать ссылки на EntityManager экземпляры друг к другу, чтобы вносить изменения в один сделка. Контейнер Java EE управляет жизненным циклом менеджерами сущностей, управляемыми контейнерами.

Чтобы получить экземпляр EntityManager, введите администратор сущности в компонент приложения:

@PersistenceContext 
EntityManager em; 

Менеджеры, управляемые приложениями

С менеджером сущности, управляемым приложениями, с другой стороны стороны, контекст персистентности не распространяется на приложение компонентов и жизненного цикла экземпляров EntityManager управляется приложения.

Администраторы сущностей, управляемых приложениями, используются, когда приложения должны доступ к контексту персистентности, который не распространяется с помощью JTA транзакция по экземплярам EntityManager в определенной степени Блок. В этом случае каждый EntityManager создает новую изолированную контекст постоянства. EntityManager и связанное с ним постоянство контекст создается и уничтожается явным образом приложением. Oни также используются, когда прямое вложение экземпляров EntityManager не может быть потому что экземпляры EntityManager не являются потокобезопасными. Экземпляры EntityManagerFactory являются потокобезопасными.

http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

Ответ 4

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

Начните изучать различные настройки изоляции и применяйте правильные настройки в соответствии с вашими потребностями. Существует компромисс между точностью и скоростью. http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

Ответ 5

Я отключусь на три года:), но в том, что касается инъекций EntityManager в EJB, вот ссылка на запись в блоге Adam Bien http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

копирование:

"Вы можете ввести EntityManager непосредственно в EJB. Но: это потокобезопасный?:

@Stateless
public class BookServiceBean implements BookService {


  @PersistenceContext EntityManager em;

  public void create(Book book) { this.em.persist(book);}

 }

"

и ответ: снова скопируйте-вставить:

"Работа с EJB без какой-либо дополнительной настройки является потокобезопасной, независимо от того, вы одновременно используете один метод или несколько методов. Контейнер заботится о сериализации вызовов.",

который, возможно, может быть более ясным, но это означает, что вы можете ввести EntityManager в сеанс без состояния beans и не беспокоиться об ошибках EntityManager concurrency.