天天看点

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 注解可以实现的)的方法,不用重写。

对于需要判断并拼接查询条件的方法,我们可以在实现类中进行重写。

继续阅读