Hibernate SessionFactory vs. JPA EntityManagerFactory

Jawaban:

365

Lebih suka EntityManagerFactorydan EntityManager. Mereka didefinisikan oleh standar JPA.

SessionFactorydan Sessionkhusus untuk hibernasi. The EntityManagermemanggil sesi hibernasi di bawah tenda. Dan jika Anda memerlukan beberapa fitur spesifik yang tidak tersedia di EntityManager, Anda dapat memperoleh sesi dengan menelepon:

Session session = entityManager.unwrap(Session.class);
Bozho
sumber
2
@elpisu - Sebenarnya saya tidak bisa merekomendasikan. Saya hanya menggunakan dokumentasi resmi sebagai sumber belajar (setidaknya dalam 2 tahun terakhir), jadi saya tidak tahu apa pun yang dapat diandalkan. Tapi dokumennya cukup bagus.
Bozho
7
@ Bozho Saya tahu ini sudah terlambat, tetapi apa kekurangan menggunakan SessionFactory dan Session? Mengapa penggunaan JPA lebih disukai? Terima kasih
Mickael Marrache
12
@MickaelMarrache penggunaan JPA lebih disukai daripada API Hibernate, karena ini adalah standar Java Enterprise. Menggunakan JPA (dan membatasi diri Anda untuk itu, tanpa menggunakan fitur-fitur khusus Hibernate) meningkatkan portabilitas aplikasi, yaitu Anda memiliki opsi untuk beralih ke kerangka kerja persistensi yang berbeda dengan perubahan minimal pada aplikasi Anda, selama kerangka itu juga sesuai dengan standar JPA .
László van den Hoek
2
Apakah ini lebih baik hanya karena itu merupakan standar perusahaan? Saya meragukan itu. Standar biasanya lambat untuk berkembang dan rumit. Bagaimana dengan beberapa manfaat kehidupan nyata? JPA lebih baik karena memiliki TypedQuery, membuat Anda berhenti mengetik di semua tempat.
Bastian Voigt
1
Apakah pendekatan ini untuk mendapatkan Sessiondari EntityManager, sama dengan SessionFactory.getCurrentSession()? Maksud saya, apakah itu akan terbuka baru Sessionjika belum dibuat? Bagaimana cara kerjanya di lingkungan multithreaded?
Sarvesh
32

Saya ingin menambahkan ini bahwa Anda juga bisa mendapatkan sesi Hibernate dengan memanggil getDelegate()metode dari EntityManager.

ex:

Session session = (Session) entityManager.getDelegate();
toytoy
sumber
28
Catatan bahwa unwrap()ini lebih disukai lebih getDelegate()sesuai dengan docs java: JavaEE 6 , dan JavaEE 7 .
ryenus
22

Saya lebih suka JPA2 EntityManagerAPI daripada SessionFactory, karena rasanya lebih modern. Satu contoh sederhana:

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;
}

Saya pikir sudah jelas bahwa yang pertama terlihat lebih bersih dan juga lebih mudah untuk diuji karena EntityManager dapat dengan mudah diejek.

Bastian Voigt
sumber
30
Anda dapat membuat kode apa pun menjadi rumit jika Anda mau. return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
WST
Seberapa langsung Anda mendapatkan entitasManager dan Anda menunjukkan bahwa Anda harus menggunakan sessionfactory untuk mengambil sesi ..: D
JavaLearner
21

Menggunakan pendekatan EntityManagerFactory memungkinkan kita untuk menggunakan anotasi metode panggilan balik seperti @PrePersist, @ PostPersist, @ PreUpdate tanpa konfigurasi tambahan.

Menggunakan panggilan balik yang serupa saat menggunakan SessionFactory akan membutuhkan upaya ekstra.

Dokumen hibernasi terkait dapat ditemukan di sini dan di sini .

Pertanyaan SOF terkait dan diskusi Forum Musim Semi

Kumar Sambhav
sumber
21

SessionFactory vs. EntityManagerFactory

Seperti yang saya jelaskan dalam Panduan Pengguna Hibernate , Hibernate SessionFactorymemperluas JPA EntityManagerFactory, seperti yang diilustrasikan oleh diagram berikut:

Hubungan JPA dan Hibernate

Jadi, SessionFactoryini juga merupakan JPA EntityManagerFactory.

Baik SessionFactorydan EntityManagerFactorymetadata pemetaan entitas dan memungkinkan Anda untuk membuat Hibernate Sessionatau EntityManager.

Session vs. EntityManager

Sama seperti SessionFactorydan EntityManagerFactory, Hibernate Sessionmemperluas JPA EntityManager. Jadi, semua metode yang ditentukan oleh EntityManagertersedia di HibernateSession .

The Sessiondan `EntityManager menerjemahkan transisi status entitas ke dalam pernyataan SQL, seperti SELECT, INSERT, UPDATE, dan DELETE.

Hibernate vs. JPA bootstrap

Saat mem-bootstrap aplikasi JPA atau Hibernate, Anda memiliki dua pilihan:

  1. Anda dapat mem-bootstrap melalui mekanisme asli Hibernate, dan membuat SessionFactoryvia BootstrapServiceRegistryBuilder. Jika Anda menggunakan Spring, bootstrap Hibernate dilakukan melalui LocalSessionFactoryBean, seperti yang diilustrasikan oleh contoh GitHub ini .
  2. Atau, Anda dapat membuat JPA EntityManagerFactorymelalui Persistencekelas atau EntityManagerFactoryBuilder. Jika Anda menggunakan Spring, bootstrap JPA dilakukan melalui LocalContainerEntityManagerFactoryBean, seperti yang diilustrasikan oleh contoh GitHub ini .

Bootstrap melalui JPA lebih disukai. Itu karena JPA FlushModeType.AUTOadalah pilihan yang jauh lebih baik daripada warisan FlushMode.AUTO, yang memecah konsistensi baca-Anda-tulis untuk kueri SQL asli .

Bongkar JPA untuk Hibernate

Juga, jika Anda bootstrap melalui JPA, dan Anda telah menyuntikkan EntityManagerFactorymelalui @PersistenceUnitanotasi:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Anda dapat dengan mudah mendapatkan akses ke dasar Sessionfactorymenggunakan unwrapmetode:

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);

Hal yang sama dapat dilakukan dengan JPA EntityManager. Jika Anda menyuntikkan EntityManagermelalui @PersistenceContextanotasi:

@PersistenceContext
private EntityManager entityManager;

Anda dapat dengan mudah mendapatkan akses ke dasar Sessionmenggunakan unwrapmetode:

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

Kesimpulan

Jadi, Anda harus mem-bootstrap melalui JPA, menggunakan EntityManagerFactorydan EntityManager, dan hanya membuka mereka ke antarmuka Hibernate terkait ketika Anda ingin mendapatkan akses ke beberapa metode khusus Hibernate yang tidak tersedia di JPA, seperti mengambil entitas melalui pengidentifikasi alami .

Vlad Mihalcea
sumber
2

Dengan menggunakan EntityManager, kode tidak lagi dipasangkan dengan hibernate. Namun untuk ini, dalam penggunaannya kita harus menggunakan:

javax.persistence.EntityManager

dari pada

org.hibernate.ejb.HibernateEntityManager

Demikian pula, untuk EntityManagerFactory, gunakan antarmuka javax. Dengan begitu, kodenya secara longgar digabungkan. Jika ada implementasi JPA 2 yang lebih baik daripada hibernate, beralih akan mudah. Dalam kasus ekstrim, kita bisa mengetikkan cast ke HibernateEntityManager.

Sairam Krish
sumber
2

EntityManagerFactory adalah implementasi standar, itu sama di semua implementasi. Jika Anda memigrasikan ORM Anda ke penyedia lain seperti EclipseLink, tidak akan ada perubahan dalam pendekatan untuk menangani transaksi. Sebaliknya, jika Anda menggunakan pabrik sesi hibernate, itu terkait dengan API hibernasi dan tidak dapat bermigrasi ke vendor baru.

ABODE
sumber
1

Antarmuka EntityManager mirip dengan sessionFactory di hibernasi. EntityManager di bawah paket javax.persistance tetapi sesi dan sessionFactory di bawah paket org.hibernate.Session / sessionFactory.

Manajer entitas adalah spesifik JPA dan session / sessionFactory spesifik untuk hibernasi.

Avvappa Hegadyal
sumber
Jawaban Anda benar, tetapi pada dasarnya sama dengan jawaban yang disebut Sangyun Lee dalam komentarnya ... jadi duplikat.
RWC