1 什么是JPA
1.1 JPA概念
JPA是Java Persistence API 的简称,中文名Java持久层API,是JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.
JPA有EJB3.0软件专家组开发,作为JSR-220实现的一部分.但它又不限于EJB3.0,你可以在Web应用,甚至桌面应用中使用.JPA的宗旨是为POJO提供持久化标准规范.总的来说,JPA包括以下3方面的技术:
1. ORM映射元数据,JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
2. JPA的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来;
3. 查询语言,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合.
1.2 什么是ORM
ORM(Object-Relational Mapping) 表示对象关系映射.在面向对象的软件开发中,通过ORM,就可以吧对象映射到关系型数据库中.只要有一套程序能够做到建立对象与数据库的关联,操作对象就可以直接操作数据库数据,就可以说这套程序实现了ORM对象关系映射.简单地说:ORM就是建立实体类和数据库表之间的关系,从而达到操作实体类就相当于操作数据库表的目的.
1.3 jpa的优势
a.标准化
JPA是JCP组织发布的JavaEE标准之一,因此任何声称符合JPA标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行.
b.容器级特性的支持
JPA框架中支持大数据集,事务,并发等容器级事务,这使得JPA超越了简单持久化框架的局限,在企业应用发挥更大的作用
c.简单方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者很容易的掌握,JPA基于非入侵式原则设计,因此可以很容易的和其他框架或者容器集成
d.查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物.JPA定义了独特的JPQL(Java Persistence Query Language),JPQL 是EJB QL 的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改,JOIN,GROUP BY,HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询.
e.高级特性
JPA中能够支持面向对象的高级特性,如类之间的集成,多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化
2 什么是SpringDataJpa
Spring Data JPA框架,主要针对的就是 Spring 唯一没有简化到的业务逻辑代码,至此,开发者连仅剩的实现持久层业务逻辑的工作都省了,唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成.
Spring data jpa是在JPA规范下提供了Repository层的实现,但是使用哪一种ORM需要你来决定(默认使用Hibernate JPA的实现).虽然ORM框架都实现了JPA规范,但是在不同的ORM框架之间切换仍然需要编写不同的代码,而通过使用Spring data jpa能够方便大家在不同的ORM框架之间进行切换而不要更改代码.并且spring data jpa 对Repository层封装的很好,也省去了不少的麻烦.
3 JPA入门
1.创建数据库
2.创建项目|导入依赖
pom.xml
UTF-8 5.0.7.Final 1.9 1.9 junit junit 4.12 org.hibernate hibernate-entitymanager ${project.hibernate.version} org.hibernate hibernate-c3p0 ${project.hibernate.version} log4j log4j 1.2.17 mysql mysql-connector-java 5.1.6
3.配置文件
在src/main/resources/META-INF的文件夹下创建一个persistence.xml的配置文件.文件名不可改动必须为persistence.xml.
name:持久化单元名称
transaction-type:事务模式。
RESOURCE_LOCAL:本地事务
JTA:分布式事务
-->
org.hibernate.jpa.HibernatePersistenceProvider
可选值:create、create-drop,update、validate,none
create:程序自动创建数据库表,如果表存在则先删除后创建. 测试环境使用
create-drop:程序自动创建数据库表,如果表存在则先删除后创建. 程序结束时会删除所有表结构.测试环境使用
update:程序自动创建数据库表,如果表存在则不创建。表与映射配置如果不一致,自动修改表结构.测试环境使用
validate: 自动校验表结构.既不会创建表,也不会修改表结构
none:不会创建表,也不会修改/校验表
-->
4.创建实体类|映射
package cn.abc.pojo;
import javax.persistence.*;
@Entity
@Table(name ="cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name ="cust_id")
private long custId;
@Column(name="cust_name")
private StringcustName;
@Column(name="cust_source")
private StringcustSource;
@Column(name="cust_industry")
private StringcustIndustry;
@Column(name="cust_level")
private StringcustLevel;
@Column(name="cust_address")
private StringcustAddress;
@Column(name="cust_phone")
private StringcustPhone;
public long getCustId() {
return custId;
}
public void setCustId(long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
}
5.书写测试代码
import cn.abc.pojo.Customer;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class CustomerTest {
@Test
public void testAddCustomer()throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
EntityManager entityManager = factory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Customer customer =new Customer();
customer.setCustName("悔创阿里杰克马");
entityManager.persist(customer);
transaction.commit();
//transaction.rollback();
entityManager.close();
factory.close();
}
}
建表成功:
4 配置详解
4.1 persistence.xml
org.hibernate.jpa.HibernatePersistenceProvider
4.2 实体映射注解
4.2.1 @Entity
4.2.2 @Table
4.2.3 @Id
4.2.4 @Column
4.2.5 @GeneratedValue
5. API详解
5.1 Persistence
Persistence对象主要作用是用于获取EntityManagerFactory对象的.通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory.
/** 详解Persistence对象* 功能:* 1.读取配置文件* 2.创建EntityManagerFactory**/
public class PersistenceDemo {
@Test
public void fun1(){
//读取配置文件并创建
EntityManagerFactory EntityManagerFactory abc = Persistence.createEntityManagerFactory("abc");
}
}
5.2 EntityManagerFactory
EntityManagerFactory接口主要用来创建EntityManager实例
/* * 详解EntityManagerFactory对象
功能:
创建EntityManager
注意: 1.该对象消耗内存资源较大
2.该对象线程安全
结论: 要确保在项目中,EntityManagerFactory只创建一个实例
*/
public class EntityManagerFactory {
@Test
public void fun(){
//读取配置文件并创建
EntityManagerFactory javax.persistence.EntityManagerFactory factory = Persistence.createEntityManagerFactory("abc");
//创建EntityManager EntityManager entityManager = factory.createEntityManager();
}
}
5.3 EntityManager
在JPA规范中,EntityManager是完成持久化操作的核心对象.实体类作为普通java对象,只有在调用EntityManager将其持久化后才会变成持久化对象.EntityManager对象在一组实体类与底层数据源之间进行O/R 映射的管理.它可以用来管理和更新Entity Bean,根据主键查找Entity Bean,还可以通过JPQL语句查询实体.
我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作
5.3.1 基础增删改查
5.3.1.1 增
Customer c = new Customer();
c.setCustName("不识美人刘强东");
entityManager .persist(c);
5.3.1.2 查
5.3.1.2.1查(立即加载)
//查询主键值为1L的Customer对象
//ps:主键由于pojo类的Id属性为long类型且建表时默认最大长度 故填入long类型
Customer c =entityManager.find(Customer.class,1L);
System.out.pringln("==========");
System.out.pringln(c);
5.3.1.2.2查(延迟加载)
//查询主键值为1L的Customer对象
Customer c = entityManager.getReference(Customer.class,1L);
System.out.pringln(c)
总结:二者查询打印结果一直,区别在于执行顺序,立即加载的find方法执行时会立即查询数据库
而延迟加载getReference方法在执行时不会查询数据库,使用查询结果时才会查询
5.3.1.3 改
5.3.1.3.1 先查后改(推荐)
//查询主键值为1L的Customer对象
Customer c = manager.find(Customer.class,1L);
c.setCustName("家里最丑刘亦菲");
entityManager.merge(c); //修改
5.3.1.3.2 自己创建对象修改(注意属性值丢失,尽量用上一个)
Customer c = new Customer();
c.setCustId(1L);
c.setCustName("家里最丑刘亦菲");
entityManager.merge(c); //修改
5.3.1.4 删
//查询出对象
Customer c = entityManager.find(Customer.class,1L);
//删除对象
manager.remove(c);
5.3.2 JPQL
JPQL全称 Java Persistence Query Language,基于首次在EJB2.0中引入的EJB查询语言(EJBQL),Java持久化查询语言(JPQL)是一种可移植的查询语言,诣在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起,使用这种语言编写的查询时可移植的,可以被编译成所有主流数据库服务器上的SQL.
其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表明和表的属性
5.3.2.1 基础查询
//书写JPQL语句
//String jpql = "select c from cn.abc.pojo.Customer.java c";
//String jpql = "select c from Customer c";
String jpql = "from Customer";
//ps:以上三种效果一致
//将JPQL语句封装为查询对象
Query query = entityManager.createQuery(jpql);
//查询并返回结果
List
list = query.getResultList(); System.out.println(list);
5.3.2.2 分页查询
//书写JPQL语句
String jpql = "from Customer";
//封装到Query对象中
Query query = entityManager.createQuery(jpql);
//设置分页参数 limit ?,?
query.setFirstResult(0); //第一个问号 从第几页开始
query.setMaxResults(2); //第二个问号 每页读几个
//执行并获得查询结果
List
list = query.getResultList(); System.out.println(list);
5.3.2.3 条件查询
5.3.2.3.1 问号占位符
//书写JPQL语句
String jpql = "from Customer where custName like ?";
//封装到Query对象中
Query query = entityManager.createQuery(jpql);
//指定占位符的值
query.setParameter(1,"%撒%");
//执行并获得查询结果
List
list = query.getResultList(); System.out.println(list);
5.3.2.3.2 命名占位符
//书写JPQL语句
String jpql = "from Customer where custName like :hehe";
//封装到Query对象中
Query query = entityManager.createQuery(jpql);
//指定占位符的值
query.setParameter("hehe","%撒%");
//执行并获得查询结果
List
list = query.getResultList(); System.out.println(list);
5.3.2.4 排序
//书写JPQL语句
String jpql = "from Customer order by custId desc";
//封装到Query对象中
Query query = entityManager.createQuery(jpql);
//执行并获得查询结果
List
list = query.getResultList(); System.out.println(list);
5.3.2.5 聚合函数
//书写JPQL语句
String jpql1 = "select count(c) from Customer c ";
String jpql2 = "select sum(c.custId) from Customer";
String jpql3 = "select avg(c.custId) from Customer";
String jpql4 = "select max(c.custId) from Customer";
String jpql5 = "select min(c.custId) from Customer";
//封装到Query对象中
Query query = entityManager.createQuery(jpql5);
//执行并获得查询结果
Number num = (Number) query.getSingleResult();
System.out.println(num);
5.3.3 EntityTransaction
/* 详解EntityTransaction对象
功能:
事务管理对象,用于管理事务
事务开启/提交/回滚...
*/
//读取配置文件并创建
EntityManagerFactoryjavax.persistence.EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//创建EntityManager
EntityManager entityManager = factory.createEntityManager();
System.out.println("-----------以下为transaction对象-------------");
//获得Transaction对象
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();//开启事务
transaction.commit();//提交事务
transaction.rollback();//回滚事务