天天看點

JPA與Hibernate差別及之間的關系

分享知識 傳遞快樂

JPA與Hibernate 的差別

JPA和Hibernate之間的最大的差別是:

  • JPA是一個規範,不是架構
  • Hibernate是JPA的實作

也可以簡單的了解為JPA是标準接口,Hibernate是實作。

那麼Hibernate是如何實作與JPA的這種關系的呢?

Hibernate主要是通過三個元件來實作的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。

  • hibernate-annotation:是Hibernate支援annotation方式配置的基礎,它包括了标準的JPA annotation以及Hibernate自身特殊功能的annotation。
  • hibernate-core:是Hibernate的核心實作,提供了Hibernate所有的核心功能。
  • hibernate-entitymanager:實作了标準的JPA,可以把它看成hibernate-core和JPA之間的擴充卡,它并不直接提供ORM的功能,而是對hibernate-core進行封裝,使得Hibernate符合JPA的規範。

下面一結構圖充分展示了JPA 與 ORM架構關系:

JPA與Hibernate差別及之間的關系
下面重點介紹一下 hibernate-entitymanager 包的主要類及實作:

HibernatePersistence.java實作了JPA的PersistenceProvider接口,它提供createEntityManagerFactory和createContainerEntityManagerFactory兩個方法來建立EntityManagerFactory對象,這兩個方法底層都是調用的EJB3Configuration對象的buildEntityManagerFactory方法,來解析JPA配置檔案persistence.xml,,并建立EntityManagerFactory對象。

EntityManagerFactory對象的實作是EntityManagerFactoryImpl類,這個類有一個最重要的private屬性就是Hibernate的核心對象之一SessionFactory。這個類最重要的方法是createEntityManager,來傳回EntityMnagaer對象,而sessionFactory屬性也傳入了該方法。

EntityManager對象的實作是EntityManagerImpl類,這個類繼承自AbstractEntityManagerImpl類,在AbstractEntityManager類中有一個抽象方法getSession來獲得Hibernate的Session對象,正是在這個Session對象的實際支援下,EntityManagerImpl類實作了JPA的EntityManager接口的所有方法,并完成實際的ORM操作。

此外,hibernate-entitymanager包中還有QueryImpl類利用EntityManagerImpl的支援實作了JPA的Query接口;TransactionImpl利用EntityManagerImpl的支援實作了JPA的EntityTransaction接口。

至此,Hibernate通過hibernate-entitymanager包完成了對于JPA的全部支援工作。

注意:

JPA中的Query對象的getSingleResult()方法,當查詢不到結果時,抛出NoResultException、當查詢到多個結果時,抛出NonUniqueResultException;并且NoResultException和NonUniqueResultException都是RuntimeException。

擴充:

Spring Data JPA是什麼?以及相關概述

  • 其次Spring也想要做持久化相關工作,并且已有Spring-data-**這一系列包(Spring-data-jpa,Spring-data-template,Spring-data-mongodb等)。
  • 其中Spring-data-jpa即代表着,Spring架構對JPA的整合。
  • Spring Data JPA是在JPA規範的基礎下提供了Repository層的實作。

在項目中的repository層中具體表現為:

1.接口要繼承JpaRepository接口示

例代碼如下:

@Entity
@Table(name = "t_user")//資料庫中表名
public class UserEO {
    @Id
    @Column(name = "USER_ID")//資料庫中字段名
    private String userId;

    @Column(name = "USER_NAME")
    private String  userName;
   
}


@Repository
public interface UserRepository extends JpaRepository<UserEO,String>{//第二個參數是UserEO對應的表的主鍵類型

    //直接定義如下方法,不需要寫具體的sql語句
   List<UserEO> findByUserName(String userName);

    //對于自定義操作(比如更新狀态字段為 ‘1’)使用 @Query注解
    @Query("update UserEO u set u.status = '1' where u.userName = :userName    
    void updateStatusByName(String userName);


    //此方法 需要拼接條件  在實作類中重寫
     List<UserEO> findByUserName(Condition condition);

}      

2.實作類無需顯式實作 UserRepository,隻要命名為UserRepositoryImpl即可。

好處在于對于不需要寫sql或者sql語句不複雜(使用 @Query 注解可以實作的)的方法,不用重寫。

對于需要判斷并拼接查詢條件的方法,我們可以在實作類中進行重寫。

繼續閱讀