Различные способы получения EntityManager
Обычная идиома, которую я вижу для создания EntityManager, выглядит примерно так:
public class BaseDao {
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
Тогда это используется так:
Employee emp = new Employee();
emp.setName("Joe M");
getEntityManager().persist(emp);
Вопрос: почему бы не сделать это так:
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
private EntityManager entityManager = null;
public void setEntityManger() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
this.entityManager = factory.createEntityManager();
}
public EntityManager getEntityManager() {
return this.entityManager;
}
}
Другими словами, есть ли необходимость всегда получать менеджер сущностей через factory.createEntityManager()
? или он может быть создан как переменная экземпляра (или даже статическая переменная) и получен таким образом?
Чтобы уточнить, я говорю о среде, которая не использует контейнеры EJB или Spring.
Благодарю.
Ответы
Ответ 1
Существует два способа создания экземпляров EntityManager
.
Один способ - для приложений SDK, и я часто использую его в модульном тестировании. Вот что у вас есть в вашем примере:
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
В корпоративных приложениях вы позволяете контейнеру создавать их для вас и вставлять их при необходимости.
EntityManager
- это просто оболочка для соединения JDBC. Это очень легкий вес и может быть создан и уничтожен без потери производительности.
Помните, что EntityManager
не является потокобезопасным, поэтому, если у вас есть один экземпляр, вам может потребоваться синхронизировать доступ к нему. Смотрите основы транзакций для деталей.
Вот как бы я это сделал (примерно):
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
private static EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public void create(MyEntiy person){
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// do what ever you need
em.getTransaction().commit();
em.close();
}
// add more methods to the dao.
}
Как только вы получите этот прототип и будете готовы, вы можете использовать универсальный DAO.
Ответ 2
Сегодня вам, вероятно, стоит подумать о Spring-data и @PersistanceUnit для управления вашим EntityManager.
EntityManager - это больше, чем просто оболочка-оболочка для соединения JDBC. Он определяет область действия персистентного контекста, который определяет единицу работы, которая должна выполняться при фиксации транзакции (когда вы сбрасываете запросы в базу данных). В контексте постоянства вам также гарантируется, что данный объект в базе данных приведет к тому же объекту Java, независимо от того, загружаете ли вы его напрямую или обращаетесь к нему через отношение OneToMany другого объекта.
Относительно первоначального вопроса о получении EntityManagerFactory в неподрессоренных условиях. Вы просто звоните
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
Этот метод является статическим методом фабрики, и в зависимости от реализации JPA вы либо получаете один и тот же экземпляр для того же PU, либо неглубокую оболочку, которая оборачивает основной сеанс персистентности (из которых по одному на PU).