JPA Java Persistence API, 是 Java EE 5 的标准 ORM 接口, 也是 ejb3 规范的一部分.
Hibernate, 当今很流行的 ORM 框架, 是 JPA 的一个实现, 但是其功能是 JPA 的超集.
JPA 和 Hibernate 之间的关系, 可以简单的理解为 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 的规范.
Maven 依赖:
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-entitymanager</artifactId>
- <version>4.2.4.Final</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>5.2.2.Final</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.5.6-Final</version>
- </dependency>
下面重点介绍一下 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.
这样有两个问题:
1, 我认为 getSingleResult 方法应该允许查询不到结果的情况存在的, 此时它返回 null 即可, 没有必要抛出异常;
2, 即使需要在查询不到结果或者查询到多个结果时抛出异常, 也不应该抛出 RuntimeException, 因为这样表示不需要代码显示的用 try-catch 块来捕获这些异常, 也就不会引起用户对这两个异常的重视.
目前解决这个问题我使用的方法是
- try{
- Object o = query.getSingleResult();
- } catch (NoResultException ex){
- return null;
- }catch(NonUniqueResultException ex) {
- o = queryObject.getResultList();
- return ((List)o).get(0);
- }
来源: https://www.cnblogs.com/xinglongbing521/p/10315409.html