JAVA: объект EntityManager в многопоточной среде
если у меня есть несколько потоков, каждый использует инжектор для получения объекта EntityManager, каждый из которых использует объект em для выбора списка других объектов класса. Готов к использованию в цикле for.
Если поток заканчивается первым и вызывает clear(), это повлияет на другие потоки? Как и цикл for будет иметь исключение?
Как насчет close()?
Если ответ "Это зависит", что (метод определения класса?) и где (java code? annotation? xml?) следует посмотреть, как это зависит?
Я не писал источник, я просто использую другую библиотеку без документации.
Спасибо.
Ответы
Ответ 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.