Jestem nowy w Hibernacji i nie jestem pewien, czy użyć Hibernacji, SessionFactoryczy JPA, EntityManagerFactoryaby utworzyć Hibernację Session.
Jaka jest różnica między tymi dwoma? Jakie są zalety i wady korzystania z każdego z nich?
Jestem nowy w Hibernacji i nie jestem pewien, czy użyć Hibernacji, SessionFactoryczy JPA, EntityManagerFactoryaby utworzyć Hibernację Session.
Jaka jest różnica między tymi dwoma? Jakie są zalety i wady korzystania z każdego z nich?
Odpowiedzi:
Wolę EntityManagerFactoryi EntityManager. Są one zdefiniowane w standardzie JPA.
SessionFactoryi Sessionsą specyficzne dla hibernacji. EntityManagerWywołuje sesji hibernacji pod maską. A jeśli potrzebujesz określonych funkcji, które nie są dostępne w EntityManager, możesz uzyskać sesję, dzwoniąc:
Session session = entityManager.unwrap(Session.class);
Sessionod EntityManager, tak samo jak SessionFactory.getCurrentSession()? Mam na myśli, czy otworzy się nowy, Sessionjeśli jeszcze nie został utworzony? Jak to działa w środowisku wielowątkowym?
Wolę EntityManagerAPI JPA2 niż SessionFactory, ponieważ wydaje się bardziej nowoczesny. Jeden prosty przykład:
JPA:
@PersistenceContext
EntityManager entityManager;
public List<MyEntity> findSomeApples() {
return entityManager
.createQuery("from MyEntity where apples=7", MyEntity.class)
.getResultList();
}
SessionFactory:
@Autowired
SessionFactory sessionFactory;
public List<MyEntity> findSomeApples() {
Session session = sessionFactory.getCurrentSession();
List<?> result = session.createQuery("from MyEntity where apples=7")
.list();
@SuppressWarnings("unchecked")
List<MyEntity> resultCasted = (List<MyEntity>) result;
return resultCasted;
}
Myślę, że jasne jest, że pierwszy wygląda na czystszy i łatwiej go przetestować, ponieważ EntityManager można łatwo wyśmiewać.
return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
Korzystanie z podejścia EntityManagerFactory pozwala nam korzystać z adnotacji metod wywołania zwrotnego, takich jak @PrePersist, @ PostPersist, @ PreUpdate bez dodatkowej konfiguracji.
Korzystanie z podobnych wywołań zwrotnych podczas korzystania z SessionFactory będzie wymagać dodatkowych wysiłków.
Powiązane dokumenty Hibernacja można znaleźć tutaj i tutaj .
SessionFactory vs. EntityManagerFactoryJak wyjaśniłem w Przewodniku użytkownika Hibernacji , Hibernacja SessionFactoryrozszerza JPA EntityManagerFactory, co ilustruje poniższy schemat:
Tak, SessionFactoryto również JPA EntityManagerFactory.
Zarówno SessionFactoryi EntityManagerFactoryzawierają metadane odwzorowania encji i umożliwiają utworzenie hibernacji Sessionlub a EntityManager.
Session vs. EntityManagerPodobnie jak SessionFactoryi EntityManagerFactoryHibernacja Sessionrozszerza JPA EntityManager. Tak więc wszystkie metody zdefiniowane przez EntityManagersą dostępne w Hibernacji Session.
A Sessionoraz `EntityManager tłumaczą przejścia stanu encji na instrukcje SQL, takie jak SELECT, INSERT, UPDATE i DELETE.
Podczas ładowania aplikacji JPA lub Hibernacji masz dwie możliwości:
SessionFactorypomocą BootstrapServiceRegistryBuilder. Jeśli używasz Springa, Hibernacja bootstrap odbywa się za pomocą LocalSessionFactoryBean, jak pokazano w tym przykładzie GitHub .EntityManagerFactoryza pośrednictwem Persistenceklasy lub EntityManagerFactoryBuilder. Jeśli używasz Springa, bootstrap JPA odbywa się za pomocą LocalContainerEntityManagerFactoryBean, jak pokazano w tym przykładzie GitHub .Preferowane jest ładowanie poprzez JPA. Jest tak, ponieważ JPA FlushModeType.AUTOjest znacznie lepszym wyborem niż starsza wersja FlushMode.AUTO, która łamie spójność odczytu i zapisu w rodzimych zapytaniach SQL .
Ponadto, jeśli bootstrap przez WZP, a ty wstrzyknął EntityManagerFactorypośrednictwem @PersistenceUnitadnotacji:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
Możesz łatwo uzyskać dostęp do instrumentu bazowego Sessionfactoryza pomocą unwrapmetody:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
To samo można zrobić z WZP EntityManager. Jeśli wstrzyknąć EntityManagerza pomocą @PersistenceContextadnotacji:
@PersistenceContext
private EntityManager entityManager;
Możesz łatwo uzyskać dostęp do instrumentu bazowego Sessionza pomocą unwrapmetody:
Session session = entityManager.unwrap(Session.class);
Tak więc powinieneś bootować pasek za pomocą JPA, używać EntityManagerFactoryi EntityManager, i rozpakowywać je do powiązanych interfejsów Hibernacja tylko wtedy, gdy chcesz uzyskać dostęp do niektórych specyficznych metod Hibernacji, które nie są dostępne w JPA, takich jak pobieranie encji za pomocą jej naturalnego identyfikatora .
Korzystając z EntityManager, kod nie jest już ściśle powiązany z hibernacją. Ale w tym celu w użyciu powinniśmy użyć:
javax.persistence.EntityManager
zamiast
org.hibernate.ejb.HibernateEntityManager
Podobnie dla EntityManagerFactory użyj interfejsu javax. W ten sposób kod jest luźno powiązany. Jeśli istnieje lepsza implementacja JPA 2 niż hibernacja, przełączanie byłoby łatwe. W skrajnym przypadku możemy wpisać cast do HibernateEntityManager.
EntityManagerFactory to standardowa implementacja, jest taka sama we wszystkich implementacjach. W przypadku migracji ORM dla dowolnego innego dostawcy, takiego jak EclipseLink, nie będzie żadnych zmian w podejściu do obsługi transakcji. Natomiast w przypadku korzystania z fabryki sesji hibernacji jest ona powiązana z interfejsami API hibernacji i nie można przeprowadzić migracji do nowego dostawcy.
Interfejs EntityManager jest podobny do sessionFactory w trybie hibernacji. EntityManager w pakiecie javax.persistance, ale session & sessionFactory w org.hibernate.Session / sessionFactory.
Menedżer jednostek jest specyficzny dla JPA, a sesja / sesja jest specyficzna dla hibernacji.