Tôi chưa quen với Hibernate và tôi không chắc nên sử dụng Hibernate SessionFactory
hay JPA EntityManagerFactory
để tạo Hibernate Session
.
sự khác biệt giữa hai cái đó là gì? Những ưu và nhược điểm của việc sử dụng mỗi trong số đó là gì?
Tôi chưa quen với Hibernate và tôi không chắc nên sử dụng Hibernate SessionFactory
hay JPA EntityManagerFactory
để tạo Hibernate Session
.
sự khác biệt giữa hai cái đó là gì? Những ưu và nhược điểm của việc sử dụng mỗi trong số đó là gì?
Câu trả lời:
Thích EntityManagerFactory
và EntityManager
. Chúng được xác định theo tiêu chuẩn JPA.
SessionFactory
và Session
đặc biệt ngủ đông. Việc EntityManager
gọi phiên ngủ đông dưới mui xe. Và nếu bạn cần một số tính năng cụ thể không có sẵn trong EntityManager
, bạn có thể có được phiên bằng cách gọi:
Session session = entityManager.unwrap(Session.class);
Session
từ EntityManager
, giống như SessionFactory.getCurrentSession()
? Ý tôi là, nó sẽ mở mới Session
nếu nó chưa được tạo? Làm thế nào nó hoạt động trong môi trường đa luồng?
Tôi muốn thêm vào điều này để bạn cũng có thể có được phiên của Hibernate bằng cách gọi getDelegate()
phương thức từ EntityManager
.
Ví dụ:
Session session = (Session) entityManager.getDelegate();
Tôi thích EntityManager
API JPA2 hơn SessionFactory
, vì nó cảm thấy hiện đại hơn. Một ví dụ đơn giản:
JPA:
@PersistenceContext
EntityManager entityManager;
public List<MyEntity> findSomeApples() {
return entityManager
.createQuery("from MyEntity where apples=7", MyEntity.class)
.getResultList();
}
Phiên họp:
@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;
}
Tôi nghĩ rõ ràng rằng cái đầu tiên trông sạch hơn và cũng dễ kiểm tra hơn vì EntityManager có thể dễ dàng bị chế giễu.
return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
Sử dụng phương pháp EntityManagerFactory cho phép chúng tôi sử dụng các chú thích phương thức gọi lại như @PrePersist, @ PostPersist, @ PreUpdate mà không cần cấu hình thêm.
Sử dụng các cuộc gọi lại tương tự trong khi sử dụng SessionFactory sẽ đòi hỏi thêm nỗ lực.
Tài liệu Hibernate liên quan có thể được tìm thấy ở đây và đây .
SessionFactory
so với EntityManagerFactory
Như tôi đã giải thích trong Hướng dẫn sử dụng Hibernate , Hibernate SessionFactory
mở rộng JPA EntityManagerFactory
, như được minh họa bằng sơ đồ sau:
Vì vậy, SessionFactory
cũng là một JPA EntityManagerFactory
.
Cả SessionFactory
và EntityManagerFactory
chứa siêu dữ liệu ánh xạ thực thể và cho phép bạn tạo Hibernate Session
hoặc a EntityManager
.
Session
so với EntityManager
Cũng giống như SessionFactory
và EntityManagerFactory
, Hibernate Session
mở rộng JPA EntityManager
. Vì vậy, tất cả các phương thức được xác định bởi EntityManager
có sẵn trong Hibernate Session
.
Và Session
`EntityManager dịch chuyển trạng thái thực thể thành các câu lệnh SQL, như CHỌN, CHERTN, CẬP NHẬT và XÓA.
Khi bootstrapping ứng dụng JPA hoặc Hibernate, bạn có hai lựa chọn:
SessionFactory
thông qua BootstrapServiceRegistryBuilder
. Nếu bạn đang sử dụng Spring, bootstrap Hibernate được thực hiện thông qua LocalSessionFactoryBean
, như được minh họa bằng ví dụ GitHub này .EntityManagerFactory
thông qua Persistence
lớp hoặc EntityManagerFactoryBuilder
. Nếu bạn đang sử dụng Spring, bootstrap JPA được thực hiện thông qua LocalContainerEntityManagerFactoryBean
, như được minh họa bằng ví dụ GitHub này .Bootstrapping thông qua JPA sẽ được ưu tiên. Đó là bởi vì JPA FlushModeType.AUTO
là một lựa chọn tốt hơn nhiều so với di sản FlushMode.AUTO
, phá vỡ tính nhất quán đọc-ghi của bạn cho các truy vấn SQL gốc .
Ngoài ra, nếu bạn bootstrap thông qua JPA và bạn đã tiêm EntityManagerFactory
thông qua @PersistenceUnit
chú thích:
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
Bạn có thể dễ dàng truy cập vào bên dưới Sessionfactory
bằng unwrap
phương thức:
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Điều tương tự có thể được thực hiện với JPA EntityManager
. Nếu bạn tiêm EntityManager
thông qua @PersistenceContext
chú thích:
@PersistenceContext
private EntityManager entityManager;
Bạn có thể dễ dàng truy cập vào bên dưới Session
bằng unwrap
phương thức:
Session session = entityManager.unwrap(Session.class);
Vì vậy, bạn nên bootstrap thông qua JPA, sử dụng EntityManagerFactory
và EntityManager
và chỉ hủy kết nối chúng với các giao diện Hibernate liên quan của chúng khi bạn muốn truy cập vào một số phương thức dành riêng cho Hibernate không có sẵn trong JPA, như tìm nạp thực thể thông qua định danh tự nhiên .
Bằng cách sử dụng EntityManager, mã không còn được kết hợp chặt chẽ với chế độ ngủ đông. Nhưng đối với điều này, trong sử dụng chúng ta nên sử dụng:
javax.persistence.EntityManager
thay vì
org.hibernate.ejb.HibernateEntityManager
Tương tự, đối với EntityManagerFactory, hãy sử dụng giao diện javax. Bằng cách đó, mã được ghép lỏng lẻo. Nếu có triển khai JPA 2 tốt hơn ngủ đông, việc chuyển đổi sẽ dễ dàng. Trong trường hợp cực đoan, chúng ta có thể nhập cast vào HibernateEntityManager.
EntityManagerFactory là triển khai tiêu chuẩn, nó giống nhau trên tất cả các triển khai. Nếu bạn di chuyển ORM của mình cho bất kỳ nhà cung cấp nào khác như EclipseLink, sẽ không có bất kỳ thay đổi nào trong cách tiếp cận để xử lý giao dịch. Ngược lại, nếu bạn sử dụng nhà máy phiên của hibernate, nó được gắn với API ngủ đông và không thể di chuyển sang nhà cung cấp mới.
Giao diện EntityManager tương tự như sessionFactory trong chế độ ngủ đông. EntityManager trong gói javax.persistance nhưng phiên và sessionFactory trong gói org.hibernate.Session / sessionFactory.
Trình quản lý thực thể là JPA cụ thể và session / sessionFactory là chế độ ngủ đông cụ thể.