Hibernate SessionFactory กับ JPA EntityManagerFactory


251

ฉันใหม่เพื่อ Hibernate และผมไม่แน่ใจว่าจะใช้ Hibernate SessionFactoryหรือ JPA เพื่อสร้างไฮเบอร์เนต EntityManagerFactorySession

ความแตกต่างระหว่างสองสิ่งนี้คืออะไร? ข้อดีและข้อเสียของการใช้แต่ละข้อคืออะไร


6
คำตอบสำหรับคำถามที่ซ้ำกันนี้ดีจริงๆ stackoverflow.com/questions/23445830/…
Sanghyun Lee

คำตอบ:


365

ชอบEntityManagerFactoryและEntityManager. พวกเขาถูกกำหนดโดยมาตรฐาน JPA

SessionFactoryและSessionจำศีลเฉพาะ การEntityManagerเรียกใช้เซสชันไฮเบอร์เนตภายใต้ประทุน และหากคุณต้องการคุณสมบัติเฉพาะบางอย่างที่ไม่มีในEntityManagerคุณสามารถรับเซสชันได้โดยโทร:

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

2
@elpisu - ฉันไม่สามารถแนะนำได้จริง ฉันใช้เอกสารทางการเป็นเพียงแหล่งข้อมูลการเรียนรู้ (อย่างน้อยใน 2 ปีที่ผ่านมา) ดังนั้นฉันจึงไม่ทราบว่ามีอะไรน่าเชื่อถือ แต่เอกสารนั้นดีพอ
Bozho

7
@Bozho ฉันรู้ว่ามันช้า แต่ข้อเสียของการใช้ SessionFactory และ Session คืออะไร? ทำไมจึงเลือกใช้ JPA ขอบคุณ
Mickael Marrache

12
@MickaelMarrache การใช้ JPA เป็นที่ต้องการมากกว่า Hibernate API เนื่องจากเป็นมาตรฐาน Java Enterprise การใช้ JPA (และ จำกัด การตัวคุณเองโดยไม่ใช้คุณสมบัติเฉพาะของไฮเบอร์เนต) ช่วยเพิ่มความสะดวกในการพกพาแอปพลิเคชั่นนั่นคือคุณมีตัวเลือกในการสลับไปยังเฟรมเวิร์กการคงอยู่ที่แตกต่างกัน .
László van den Hoek

2
มันจะดีกว่าเพียงเพราะมันเป็นมาตรฐานขององค์กรหรือไม่ ฉันสงสัย. มาตรฐานมักจะช้าในการพัฒนาและซับซ้อน สิ่งที่เกี่ยวกับประโยชน์ในชีวิตจริงบางอย่าง? JPA ดีกว่าเพราะมี TypedQuery ทำให้คุณไม่สามารถพิมพ์ได้ทั่วทุกที่
Bastian Voigt

1
เป็นวิธีการที่จะได้รับSessionจากEntityManagerนี้เช่นเดียวกับSessionFactory.getCurrentSession()? ฉันหมายความว่ามันจะเปิดใหม่Sessionหากยังไม่ได้สร้าง? มันทำงานอย่างไรในสภาพแวดล้อมแบบมัลติเธรด?
Sarvesh

32

ฉันต้องการเพิ่มเกี่ยวกับเรื่องนี้ว่าคุณยังสามารถได้รับเซสชั่นของ Hibernate โดยการเรียกวิธีการจากgetDelegate()EntityManager

อดีต:

Session session = (Session) entityManager.getDelegate();

28
ทราบว่าunwrap()เป็นเป็นที่ต้องการมากกว่าgetDelegate()ตามเอกสารจาวา: JavaEE 6และJavaEE 7
ryenus

22

ฉันชอบ JPA2 EntityManagerAPI มากกว่าSessionFactoryเพราะรู้สึกทันสมัยกว่านี้ ตัวอย่างง่ายๆหนึ่งตัวอย่าง:

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

ฉันคิดว่ามันชัดเจนว่าอันแรกดูสะอาดกว่าและทดสอบง่ายกว่าเพราะ EntityManager สามารถล้อเลียนได้ง่าย


30
คุณสามารถสร้างรหัสที่ซับซ้อนได้หากต้องการ return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
wst

คุณได้รับ entityManager โดยตรงอย่างไรและคุณกำลังแสดงว่าคุณต้องใช้ sessionfactory เพื่อดึงข้อมูลเซสชัน .. : D
JavaLearner

21

การใช้วิธีการ EntityManagerFactory ช่วยให้เราสามารถใช้คำอธิบายประกอบวิธีการโทรกลับเช่น @PrePersist, @ PostPersist, @ PreUpdate โดยไม่มีการกำหนดค่าเพิ่มเติม

การใช้การเรียกกลับที่คล้ายกันขณะใช้ SessionFactory จะต้องใช้ความพยายามเป็นพิเศษ

เอกสาร Hibernate ที่เกี่ยวข้องสามารถดูได้ที่นี่และที่นี่

คำถาม SOF ที่เกี่ยวข้องและการอภิปรายฟอรัมฤดูใบไม้ผลิ


21

SessionFactory เมื่อเทียบกับ EntityManagerFactory

ดังที่ฉันได้อธิบายไว้ในคู่มือผู้ใช้ไฮเบอร์เนตไฮเบอร์เนตจะSessionFactoryขยาย JPA EntityManagerFactoryดังที่แสดงในแผนภาพต่อไปนี้:

ความสัมพันธ์ JPA และไฮเบอร์เนต

ดังนั้นSessionFactoryยังเป็น EntityManagerFactoryJPA

ทั้งสองSessionFactoryและEntityManagerFactoryประกอบด้วยข้อมูลเมตาทำแผนที่นิติบุคคลและช่วยให้คุณสามารถสร้าง Hibernate หรือSessionEntityManager

Session เมื่อเทียบกับ EntityManager

เช่นเดียวกับSessionFactoryและEntityManagerFactoryการ Hibernate Sessionขยาย EntityManagerJPA ดังนั้นวิธีการทั้งหมดที่กำหนดโดยที่EntityManagerมีอยู่ในไฮเบอร์เนตSessionมีอยู่ในไฮเบอร์เนต

Sessionและ `EntityManager แปลเปลี่ยนสถานะนิติบุคคลลงในคำสั่ง SQL เช่น SELECT, INSERT, UPDATE และลบ

ไฮเบอร์เนตกับ JPA bootstrap

เมื่อทำการบู๊ตแอปพลิเคชั่น JPA หรือไฮเบอร์เนตคุณมีสองทางเลือก:

  1. คุณสามารถบูตผ่านกลไกพื้นเมือง Hibernate และสร้างผ่านทางSessionFactory BootstrapServiceRegistryBuilderหากคุณใช้ Spring การบูตไฮเบอร์เนตจะทำผ่านทางLocalSessionFactoryBeanดังที่แสดงในตัวอย่าง GitHubนี้
  2. หรือคุณสามารถสร้าง JPA EntityManagerFactoryผ่านชั้นหรือPersistence EntityManagerFactoryBuilderหากคุณใช้งาน Spring บูตของ JPA จะทำผ่านทางLocalContainerEntityManagerFactoryBeanดังที่แสดงในตัวอย่าง GitHubนี้

ต้องการการบู๊ตผ่าน JPA นั่นเป็นเพราะ JPA FlushModeType.AUTOเป็นทางเลือกที่ดีกว่าเดิมFlushMode.AUTOซึ่งแบ่งอ่านของคุณเขียนความสอดคล้องสำหรับแบบสอบถาม SQL พื้นเมือง

เลิกใช้ JPA เพื่อไฮเบอร์เนต

นอกจากนี้หากคุณบูตบู๊ตผ่าน JPA และคุณฉีดEntityManagerFactoryผ่าน@PersistenceUnitหมายเหตุประกอบ:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

คุณสามารถเข้าถึงต้นแบบSessionfactoryโดยใช้unwrapวิธีการ:

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

เดียวกันสามารถทำได้ด้วย EntityManagerJPA หากคุณฉีดEntityManagerผ่าน@PersistenceContextหมายเหตุประกอบ:

@PersistenceContext
private EntityManager entityManager;

คุณสามารถเข้าถึงต้นแบบSessionโดยใช้unwrapวิธีการ:

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

ข้อสรุป

ดังนั้นคุณควรบูตผ่าน JPA ใช้EntityManagerFactoryและEntityManagerและมีเพียงแกะเหล่านั้นไปยังเฟซ Hibernate เกี่ยวข้องของพวกเขาเมื่อคุณต้องการที่จะได้รับการเข้าถึงบางวิธี Hibernate เฉพาะที่ไม่สามารถใช้ได้ใน JPA เช่นการเรียกนิติบุคคลผ่านตัวระบุตามธรรมชาติของมัน


2

โดยใช้ EntityManager รหัสจะไม่คู่กับโหมดไฮเบอร์เนตอย่างแน่นหนาอีกต่อไป แต่สำหรับสิ่งนี้ในการใช้งานเราควรใช้:

javax.persistence.EntityManager

แทน

org.hibernate.ejb.HibernateEntityManager

ในทำนองเดียวกันสำหรับ EntityManagerFactory ให้ใช้อินเตอร์เฟส javax ด้วยวิธีนี้รหัสจะถูกรวมเข้าด้วยกันอย่างหลวม ๆ หากมีการใช้ JPA 2 ที่ดีกว่าการจำศีลการสลับจะเป็นเรื่องง่าย ในกรณีที่รุนแรงเราสามารถพิมพ์ cast ไปที่ HibernateEntityManager


2

EntityManagerFactory เป็นการใช้งานมาตรฐานมันเหมือนกันในทุกการใช้งาน หากคุณย้าย ORM ของคุณสำหรับผู้ให้บริการรายอื่นเช่น EclipseLink จะไม่มีการเปลี่ยนแปลงใด ๆ ในวิธีการจัดการธุรกรรม ในทางตรงกันข้ามหากคุณใช้โรงงานเซสชันของไฮเบอร์เนตจะเชื่อมโยงกับ API ไฮเบอร์เนตและไม่สามารถย้ายไปยังผู้จัดจำหน่ายรายใหม่ได้


1

อินเทอร์เฟซ EntityManager คล้ายกับ sessionFactory ในโหมดไฮเบอร์เนต EntityManager ภายใต้แพ็คเกจ javax.persistance แต่เซสชันและ sessionFactory ภายใต้ org.hibernate.Session / sessionFactory แพ็คเกจ

ผู้จัดการเอนทิตีเป็น JPA เฉพาะและเซสชั่น / sessionFactory เป็นไฮเบอร์เนตเฉพาะ


คำตอบของคุณถูกต้อง แต่ก็เป็นคำตอบเดียวกับคำตอบของ Sangyun Lee ในความคิดเห็นของเขา ...
RWC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.