分享知识 传递快乐
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框架关系:
下面重点介绍一下 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 注解可以实现的)的方法,不用重写。
对于需要判断并拼接查询条件的方法,我们可以在实现类中进行重写。