Jestem nowy w Hibernacji i nie jestem pewien, czy użyć Hibernacji, SessionFactory
czy JPA, EntityManagerFactory
aby 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, SessionFactory
czy JPA, EntityManagerFactory
aby utworzyć Hibernację Session
.
Jaka jest różnica między tymi dwoma? Jakie są zalety i wady korzystania z każdego z nich?
Odpowiedzi:
Wolę EntityManagerFactory
i EntityManager
. Są one zdefiniowane w standardzie JPA.
SessionFactory
i Session
są specyficzne dla hibernacji. EntityManager
Wywoł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);
Session
od EntityManager
, tak samo jak SessionFactory.getCurrentSession()
? Mam na myśli, czy otworzy się nowy, Session
jeśli jeszcze nie został utworzony? Jak to działa w środowisku wielowątkowym?
Wolę EntityManager
API 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. EntityManagerFactory
Jak wyjaśniłem w Przewodniku użytkownika Hibernacji , Hibernacja SessionFactory
rozszerza JPA EntityManagerFactory
, co ilustruje poniższy schemat:
Tak, SessionFactory
to również JPA EntityManagerFactory
.
Zarówno SessionFactory
i EntityManagerFactory
zawierają metadane odwzorowania encji i umożliwiają utworzenie hibernacji Session
lub a EntityManager
.
Session
vs. EntityManager
Podobnie jak SessionFactory
i EntityManagerFactory
Hibernacja Session
rozszerza JPA EntityManager
. Tak więc wszystkie metody zdefiniowane przez EntityManager
są dostępne w Hibernacji Session
.
A Session
oraz `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:
SessionFactory
pomocą BootstrapServiceRegistryBuilder
. Jeśli używasz Springa, Hibernacja bootstrap odbywa się za pomocą LocalSessionFactoryBean
, jak pokazano w tym przykładzie GitHub .EntityManagerFactory
za pośrednictwem Persistence
klasy 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.AUTO
jest 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ął EntityManagerFactory
pośrednictwem @PersistenceUnit
adnotacji:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
Możesz łatwo uzyskać dostęp do instrumentu bazowego Sessionfactory
za pomocą unwrap
metody:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
To samo można zrobić z WZP EntityManager
. Jeśli wstrzyknąć EntityManager
za pomocą @PersistenceContext
adnotacji:
@PersistenceContext
private EntityManager entityManager;
Możesz łatwo uzyskać dostęp do instrumentu bazowego Session
za pomocą unwrap
metody:
Session session = entityManager.unwrap(Session.class);
Tak więc powinieneś bootować pasek za pomocą JPA, używać EntityManagerFactory
i 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.