原文发布于:http://www.gufeng.tech/  谷风的个人主页

    JPA全称Java Persistence API即Java持久化API,是一种通过注解或者XML配置描述映射关系来实现将实体持久化到数据库的一种java持久化实现方案。JPA和JDBC一样,都是jdk提供的API,各厂商提供实现,目前的实现有Apache的OpenJPA以及应用广泛的Hibernate,当然还有其它的实现,这里就不一一列出了。JAP作为一种标准,已经获得了JavaEES容器的支持,同时也仍然可以在JavaSE环境中使用,这就奠定了它可被广泛应用的前提。


    JPA在随着SpringBoot的默认支持,再次被广泛提及、应用。作为一种ORM的技术,除了拥有ORM的特点之外,还有一些它自己的特点:

1 标准化

JPA是java标准化组织JCP提出的一项持久化标准,所以其任何实现都提供了相同的API,即便更换了实现方案,兼容性也是非常好的。

2 更面向对象

JPA支持面向对象中的继承、多态及多个类间的关联关系,因此使得程序员在使用JPA开发时可以方便的使用面向对象的思维,过渡性比较好。

3 功能全面

JPA支持事务、并发等特性,而不仅仅是一个简单的持久化框架,因而可以在实际使用中发挥更大的作用。

4 卓越的查询能力

    JPA是面向对象的,定义了JPQL(Java Persistence Query Language),JPQL是一种针对实体的查询语句,操作对象是实体,可以以面向对象的方式构造查询语句,在这点上类似Hibernate的HQL。JPQL能够支持批量操作(如更新和修改)、join、group by、having等子句,同时还支持子查询,因此其查询能力可见一斑。

5 集成方便

    这一点从SpringBoot选择了JPA就能够看出来。在JPA框架下创建实体只需要使用javax.persistence.Entity注解即可,其接口使用也非常简单容易上手,尤其重要的一点是JPA被设计成非***式的,天然注定了它能够被非常容易的集成。


JPA涉及的技术

1 元数据

关于映射关系,JPA同时支持注解和XML。

2 API

操作简单,将程序员从繁琐的SQL中解放出来。

3 查询语言

通过面向对象的方式进行数据查询,避免程序与SQL语句的的耦合。


    上面提及了JPA的各种好处,那么作为一种技术方案(或者叫规范),JPA有没有缺点呢?答案是肯定的,JPA将数据库关系以实体及实体间关系表示,必然存在一种将数据库的复杂概念(如一对一、一对多、多对多等关系)转移到程序中。这会带来以下一些问题:

1 程序可读性差,如果遇到特别复杂的业务逻辑,那么对于实体的定义也会非常困难,这需要设计者具有非常高的抽象、规范、设计能力。

2 数据关系发生变化时,实体必然也会发生变化。

3 将关系型数据库映射到面向对象程序上,本身就有着深度的复杂性,两者关注点不同,当关联到一起的时候必然会来带冲突。数据库关心的是数据以及数据的完整性;面向对象关心的是对象的成员及行为。


接下来介绍下JPA的一些核心类:

1 EntityManagerFactory

    EntityManagerFactory 是 EntityManager 的工厂类,负责创建 EntityManager 对象。

2 EntityManager

    EntityManager 是 JPA 应用中使用的基本对象,通过它提供的相应方法可以管理持久化对象,也可以新建或者删除持久化对象。EntityManager 还负责创建 Query 实例。在容器外使用时,EntityManagerFactory 和 EntityManager 之间是一对一的关系。

EntityTransaction

    EntityTransaction 提供 Entity 操作时需要的事务管理,和 EntityManager 是一对一的关系。在查询操作时不需要使用 EntityTransaction,而在对象持久化、状态更新、对象删除等情况下则必须使用显式的使用 EntityTransaction 的相关方法管理事务。

4 Query

    Query 是查询实体的接口,Query 对象可以从 EntityManager 中获得。根据 EJB 3.0 规范中的描述,Query 接口需要同时支持 JPQL 和原生态 SQL 两种语法。

5 Persistence

    Persistence 是一个工具类,负责根据配置文件提供的参数创建 EntityManagerFactory 对象。


最后看一段JPA的示例代码:

import javax.persistence.Column;  
import javax.persistence.Entity;  
import javax.persistence.Id;  
import javax.persistence.Table;  
  
@Entity  
@Table(name = "user")  
public class User {  
    @Id  
    @Column(name = "id")  
    private String id;  
  
    @Column(name = "name")  
    private String name;  
  
    public String getId() {  
        return id;  
    }  
  
    public void setId(String id) {  
        this.id = id;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
   
}
import javax.persistence.EntityManager;  
import javax.persistence.EntityManagerFactory;  
import javax.persistence.Persistence;  
import java.util.List;  
  
public class Main {  
    static EntityManagerFactory emf = Persistence.createEntityManagerFactory("gufengJPA");  
    static EntityManager em = emf.createEntityManager();  
  
    public static void main(String[] args) {  
        User person = new User();   
        person.setId(123456l);  
        person.setName("张无忌");  
        em.persist(person);  
  
        add(person);  
  
        System.out.println("user id:" + person.getId());  
        User user = find(person.getId());  
        System.out.println(user);  
  
        List all = findAll();  
        for (User u : all) {  
            System.out.println(u);  
        }  
  
        em.close();  
        emf.close();  
    }  
   
    public static void add(User user) {  
        em.getTransaction().begin();  
        em.persist(user);  
        em.getTransaction().commit();  
    }  
   
    public static User find(Object id) {  
        User user = em.find(User.class, id);  
        return user;  
    }  
  
    public static List findAll() {  
        List users = em.createQuery("select u from User u")  
                .getResultList();  
        return users;  
    }  
}
  
  
      
      
          
          
          
          
          
          
          
          
              
  
              
              
  
              
              
              
              
              
              
              
              
  
              
              
              
              
  
              
  
          
      

    这里需要注意的是JPA配置文件persistence.xml 必需放到类路径的根路径的META-INF文件夹下。

   

Persistence.createEntityManagerFactory("gufengJPA");

    上面这行代码是通过Java的SPI机制获得具体实现的。在hibernate的jar包里有个META-INF/services/javax.persistence.spi.PersistenceProvider 文件,这里指定的实现为 org.hibernate.jpa.HibernatePersistenceProvider。再有多个的时候,Persistence只会使用第一个。