一、什么是JPA
JPA:Java Persistence API,Java持久层API。是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
类似于JDBC,JPA是一组规范(接口),使应用程序以统一方式访问持久层。
- 具体的实现: Hibernate
- Toplink
- 其他ORM框架
JPA和Hibernate的关系
JPA 是规范: JPA 本质上就是一种 ORM 规范,不是ORM 框架 —— 因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的 API 接口,但具体实现则由 ORM 厂商提供实现;
Hibernate 是实现: Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现
JPA优势
- 标准化:提供相同的 API,这保证了基于JPA 开发的企业应用能够经过少量的修改就能够在不同的 JPA 框架下运行;
- 简单易用,集成方便:JPA 的主要目标之一就是提供更加简单的编程模型,在 JPA 框架下创建实体和创建 Java 类一样简单,只需要使用 javax.persistence.Entity 进行注释;JPA 的框架和接口也都非常简单;
- 可媲美JDBC的查询能力:JPA的查询语言是面向对象的,JPA定义了独特的JPQL,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询;
- 支持面向对象的高级特性:JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,最大限度的使用面向对象的模型。
二、JPA
1 JPA常用注解
JPA常用的注解有:
- @Entity
- @Basic
- @Table
- @Id
- @GeneratedValue
- @Column
- @Transient
- @Temporal
下面看看这些注解的具体含义。
(1)@Entity
Entity 标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。如声明一个实体类 Student,它将映射到数据库中的 student表上。
如:
@Entity
public class Student {
private int id;
private String name;
private int age;
....
}
则Student类在数据库中会对应一个数据表:student。
(2)@Table
当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。
- @Table 标注的常用选项是 name,用于指明数据库的表名
- @Table标注还有一个两个选项 catalog 和 schema 用于设置表所属的数据库目录或模式,通常为数据库名。
- uniqueConstraints 选项用于设置约束条件,通常不须设置。
如Student类映射数据库中的student_table表时,名字不同:
@Table(name = "student_table")
@Entity
public class Student {
private int id;
private String name;
private int age;
....
}
(3)@Id
@Id :用于声明一个实体类的属性映射为数据库的主键列。可置于属性的getter方法之前。
如下:属性id被设置为数据表中主键。
@Id
public int getId() {
return id;
}
(4)@GeneratedValue
@GeneratedValue:设置主键的生成策略。
有如下策略:
- IDENTITY:自增;
- AUTO:JPA默认选择策略;
- SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式;
- TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
MySQL常用自增:IDENTITY.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
(5)@@Basic
@Basic:表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为@Basic。
(6)@Column
@Column:当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明。
常用属性:name,unique 、nullable、length 等。
(7)@Transient
@Transient:表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性;
(8)@Temporal
@Temporal:在核心的 Java API 中并没有定义 Date 类型的精度(temporal precision). 而在数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备). 在进行属性映射时可使用@Temporal注解来调整精度。
2 JPA常用API
JPA中用于创建实体管理器的相关API:
- Persistence类;
- EntityManagerFactory类;
- EntityManager类;
- EntityTransaction类。
JPA中用于CRUD的相关API:
- EntityManager.find();
- EntityManager.getReference();
- EntityManager.persist();
- EntityManager.remove();
下面来看看具体的用法。
在应用执行CRUD前后需要执行如下初始化和关闭资源操作:
//----------------初始化------------------
//获取EntityManagerFactory实例
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("wgs-jpa");
//创建EntityManager 实例,EntityManager 是完成持久化操作的核心对象
EntityManager entityManager = entityManagerFactory.createEntityManager();
//EntityTransaction:管理资源层实体管理器的事务操作
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
//----------------关闭资源------------------
entityTransaction.commit();
entityManager.close();
entityManagerFactory.close();
(1)Persistence类:
Persistence 类是用于获取 EntityManagerFactory 实例。该类包含一个名为 createEntityManagerFactory 的 静态方法 。
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("wgs-jpa");
(2)EntityManagerFactory类:
EntityManagerFactory 接口主要用来创建 EntityManager 实例。该接口约定了如下4个方法:
- createEntityManager():用于创建实体管理器对象实例;
- createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map 参数用于提供 EntityManager 的属性;
- isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭;
- close():关闭 EntityManagerFactory EntityManagerFactory 关闭后将释放所有资源,isOpen()方法测试将返回 false,其它方法将不能调用,否则将导致IllegalStateException异常。
(3)EntityManager类
EntityManager 是完成持久化操作的核心对象。即将普通Java对象持久化保存到数据库当中,同时可以根据主键查找Entity Bean。
实体的状态:
- 新建状态: 新创建的对象,尚未拥有持久性主键。
- 持久化状态:已经拥有持久性主键并和持久化建立了上下文环境
- 游离状态:拥有持久化主键,但是没有与持久化建立上下文环境
- 删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。
(4)EntityTransaction类:
EntityTransaction 接口用来管理资源层实体管理器的事务操作。通过调用实体管理器的getTransaction方法 获得其实例。
EntityManager相关API:
- find (Class entityClass, Object primaryKey):返回指定的 OID
对应的实体类对象,如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的 Entity,
并加载数据库中相关信息;若 OID 不存在于数据库中,则返回一个
null。第一个参数为被查询的实体类类型,第二个参数为待查找实体的主键值; - getReference (Class entityClass,Obj