Hibernate sessionFactory so với JPA EntityManagerFactory


251

Tôi chưa quen với Hibernate và tôi không chắc nên sử dụng Hibernate SessionFactoryhay 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ì?


6
Câu trả lời này cho một câu hỏi trùng lặp là thực sự tốt. stackoverflow.com/questions/23445830/
Mạnh

Câu trả lời:


365

Thích EntityManagerFactoryEntityManager. Chúng được xác định theo tiêu chuẩn JPA.

SessionFactorySessionđặc biệt ngủ đông. Việc EntityManagergọ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);

2
@elpisu - Thật ra tôi không thể khuyên bạn. Tôi đã chỉ sử dụng tài liệu chính thức làm tài nguyên học tập (ít nhất là trong 2 năm qua), vì vậy tôi không biết gì đáng tin cậy khác. Nhưng các tài liệu là đủ tốt.
Bozho

7
@Bozho Tôi biết rằng đã muộn nhưng những hạn chế của việc sử dụng SessionFactory và Phiên là gì? Tại sao việc sử dụng JPA được ưa thích? Cảm ơn
Mickael Marrache

12
@MickaelMarrache việc sử dụng JPA sẽ được ưu tiên hơn API Hibernate, vì đây là tiêu chuẩn Java Enterprise. Sử dụng JPA (và tự giới hạn bản thân, không sử dụng các tính năng dành riêng cho Hibernate) sẽ cải thiện tính di động của ứng dụng, tức là bạn có tùy chọn chuyển sang khung duy trì khác với các thay đổi tối thiểu cho ứng dụng của mình, miễn là khung đó cũng tuân thủ tiêu chuẩn JPA .
László van den Hoek

2
Có phải tốt hơn chỉ vì nó là một tiêu chuẩn doanh nghiệp? Tôi nghi ngờ điều đó. Các tiêu chuẩn thường chậm phát triển và phức tạp. Điều gì về một số lợi ích thực tế cuộc sống? JPA tốt hơn bởi vì nó có TypedQuery, ngăn bạn không đánh máy khắp nơi.
Bastian Voigt

1
Là cách tiếp cận này để có được Sessiontừ EntityManager, giống như SessionFactory.getCurrentSession()? Ý tôi là, nó sẽ mở mới Sessionnếu nó chưa được tạo? Làm thế nào nó hoạt động trong môi trường đa luồng?
Sarvesh

32

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();

28
lưu ý rằng unwrap()sẽ được ưu tiên hơn getDelegate()theo các tài liệu java: javaee 6javaee 7 .
ryenus

22

Tôi thích EntityManagerAPI 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.


30
Bạn có thể làm cho bất kỳ mã phức tạp nếu bạn muốn. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
WST

Làm thế nào trực tiếp bạn có entityManager và bạn đang cho thấy bạn phải sử dụng sessionfactory để tìm nạp phiên ..: D
JavaLearner

21

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đây .

Câu hỏi SOF liên quanthảo luận diễn đàn mùa xuân


21

SessionFactory so với EntityManagerFactory

Như tôi đã giải thích trong Hướng dẫn sử dụng Hibernate , Hibernate SessionFactorymở rộng JPA EntityManagerFactory, như được minh họa bằng sơ đồ sau:

Mối quan hệ JPA và Hibernate

Vì vậy, SessionFactorycũng là một JPA EntityManagerFactory.

Cả SessionFactoryEntityManagerFactorychứa siêu dữ liệu ánh xạ thực thể và cho phép bạn tạo Hibernate Sessionhoặc a EntityManager.

Session so với EntityManager

Cũng giống như SessionFactoryEntityManagerFactory, Hibernate Sessionmở rộng JPA EntityManager. Vì vậy, tất cả các phương thức được xác định bởi EntityManagercó sẵn trong Hibernate Session.

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.

Hibernate so với JPA bootstrap

Khi bootstrapping ứng dụng JPA hoặc Hibernate, bạn có hai lựa chọn:

  1. Bạn có thể bootstrap thông qua cơ chế gốc Hibernate và tạo SessionFactorythô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 .
  2. Hoặc, bạn có thể tạo JPA EntityManagerFactorythông qua Persistencelớ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.AUTOlà 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 .

Unwrapping JPA để Hibernate

Ngoài ra, nếu bạn bootstrap thông qua JPA và bạn đã tiêm EntityManagerFactorythông qua @PersistenceUnitchú thích:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Bạn có thể dễ dàng truy cập vào bên dưới Sessionfactorybằng unwrapphươ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 EntityManagerthông qua @PersistenceContextchú thích:

@PersistenceContext
private EntityManager entityManager;

Bạn có thể dễ dàng truy cập vào bên dưới Sessionbằng unwrapphương thức:

Session session = entityManager.unwrap(Session.class);

Phần kết luận

Vì vậy, bạn nên bootstrap thông qua JPA, sử dụng EntityManagerFactoryEntityManagervà 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 .


2

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.


2

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.


1

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ể.


Câu trả lời của bạn là chính xác, nhưng về cơ bản giống như câu trả lời mà Sangyun Lee đề cập đến trong các bình luận của anh ấy ... vì vậy là một bản sao.
RWC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.