在讲解JPA之前先将hibernate和JPA简单的了解一下.
Hibernate概述:
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的ORM框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象变成思维来操作数据库.
JPA概述:
JPA全称为Java Persistence API,即Java持久化Api,是sun公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成.
JPA通过JDK5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.
JPA的优势:
1.标注化
JPA是JCP组织发布的JavaEE 标准之一,因此任何声称符合JPA标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行.
2.容器级特性的支持.
JPA框架中支持大数据集.事务.并发等容器级事务,这使得JPA超越了见到持久化框架的局限,在企业应用发挥更大的作用.
3.简单方便
JPA的主要目标之一就是提供更加简单的变成模型:在JPA框架下创建实体和创建Java类一样简单.没有任何的约束和限制,只需要使用javax,persistence.Entity进行注释,JPA的框架和接口也都非常简单.没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握.JPA 基于非侵入式原则设计.因此可以分容易和其他框架或者容器集成.
4.查询能力
JPA的查询语言是面向对象而非面向数据库的.它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物,JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJBQL的一种拓展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改,JOIN GROUP BY ,HAVING等通常只有SQL才能够提供的高级查询特性,甚至还能够支持子查询.
5.高级特性
JPA中能够支持面向对象的高级特性,如类之间的继承.多态和类之间的复杂关系,这样能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化.
JPA与hibernate的关系?
JPA规范本质上就是一种ORM规范,注意不是ORM框架---因为JPA并未提供ORM实现,它只是制定了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现.
JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现,JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库么?答案是否定的,也就是所,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作.
简单的入门案例:
因为JPA是sun公司制定的API规范,所以我并没有使用额外的JPA相关的Jar包,只需要导入JPA的提供商的jar包,我们选择Hibernate作为JPA的提供商,所以需要导入Hibernate的相关jar包.
可以在
这里进行下载.
JPA中的主键生成策略
通过annotation(注解)来映射hibernate实体的,基于annotation的hibernate主键标识为@Id,其生成规则由@GeneratedValue设定的,这里的@Id和@GeneratedValue都是JPA的标准用法.
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO
具体说名如下:
IDENTITY:主键由数据库自动生成(主要是自动增长型)
用法:
@Id@GeneratedValue(startegy=GenerationType.IDENTITY)private Long custId;
SQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列.
用法:一般情况为Oracle数据库
@Id@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="payablemoney_seq")@SequenceGenerator(name="payablemoney_seq",sequenceName="seq_payment")private Long custId;
//@SequenceGenerator源码中的定义@Target({TYPE,METHOD,FIELD})@Retention(RUNTIME)public @interface SequenceGenerator{//表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的"generator"值中String name();//属性表示生成策略用到的数据库序列名称String sequenceName() default "";//表示主键初始值,默认为0int initialValue() default 0;//表示每次主键值增加的大小,例如设置1,则表示每次插入新纪录后自动加1,默认为50int allocationSize() default 50;}
AUTO:主键由程序控制
用法:
@Id@GeneratedValue(strategy=GenerationType.AUTO)private Long custId;
TABLE:使用一个特定的数据库表格来保存主键
用法:
@Id @GeneratedValue(strategy = GenerationType.TABLE, generator="payablemoney_gen") @TableGenerator(name = "pk_gen", table="tb_generator", pkColumnName="gen_name", valueColumnName="gen_value", pkColumnValue="PAYABLEMOENY_PK", allocationSize=1 ) private Long custId;//@TableGenerator的定义: @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface TableGenerator { //表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中 String name(); //表示表生成策略所持久化的表名,例如,这里表使用的是数据库中的“tb_generator”。 String table() default ""; //catalog和schema具体指定表所在的目录名或是数据库名 String catalog() default ""; String schema() default ""; //属性的值表示在持久化表中,该主键生成策略所对应键值的名称。例如在“tb_generator”中将“gen_name”作为主键的键值 String pkColumnName() default ""; //属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加。例如,在“tb_generator”中将“gen_value”作为主键的值 String valueColumnName() default ""; //属性的值表示在持久化表中,该生成策略所对应的主键。例如在“tb_generator”表中,将“gen_name”的值为“CUSTOMER_PK”。 String pkColumnValue() default ""; //表示主键初识值,默认为0。 int initialValue() default 0; //表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50。 int allocationSize() default 50; UniqueConstraint[] uniqueConstraints() default {}; } //这里应用表tb_generator,定义为 : CREATE TABLE tb_generator ( id NUMBER NOT NULL, gen_name VARCHAR2(255) NOT NULL, gen_value NUMBER NOT NULL, PRIMARY KEY(id) )
JPA的API介绍
Persistence对象
Persistence对象主要作用是用于获取EntityManagerFactory对象的.通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory.
//1. 创建 EntitymanagerFactory@TestString unitName = "myJpa";EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);
EntityManagerFactory
EntityManagerFacotry接口主要用来创建EntityManager实例:
//创建实体管理类EntityManager em = factory.createEntityManager();
由于EntityManagerFactory是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory对象不会有线程问题),并且EntityManagerFactory的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory的创建进行优化,只需要做到一个工程只存在一个EntityMmanagerFactory即可/
EntityManger
在JPA规范中,EntityMmanager是完成持久化操作的核心对象,实体类作为普通java对象,只有在调用EntityManager将其持久化后才会变成持久化对象.EntityMmanager对象在一组实体类与底层数据源之间进行O/R映射的管理.它可以用来管理和更新EntityBean,根据主键查找EntityBean,还可以通过JPQL语句查询实体.
我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作.
方法说明:
getTransaction : 获取事务对象 persist : 保存操作 merge : 更新操作 remove : 删除操作 find/getReference : 根据id查询
EntityTransaction
在JPA规范中,EntityTraction是完成事务操作的核心对象,对于EntityTraction在我们的java代码中承接的功能比较简单
begin:开启事务commit:提交事务rollback:回滚事务
抽取JPAUtils工具类
package cn.itcast.dao;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;public final class JPAUtil { // JPA的实体管理器工厂:相当于Hibernate的SessionFactory private static EntityManagerFactory em; // 使用静态代码块赋值 static { // 注意:该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致 em = Persistence.createEntityManagerFactory("myPersistUnit"); } /** * 使用管理器工厂生产一个管理器对象 * * @return */ public static EntityManager getEntityManager() { return em.createEntityManager(); }}
简单的增删改查和复杂查询:
package com.qingmu;import org.hibernate.dialect.CUBRIDDialect;import org.junit.Test;import org.junit.experimental.theories.suppliers.TestedOn;import javax.persistence.*;import java.util.List;/** * @Auther:qingmu * @Description:脚踏实地,只为出人头地 * @Date:Created in 16:12 2019/5/14 */public class SpringDataJPATest02 { private EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa"); /** * 增加 */ @Test public void saveCustomer() { Customer customer = new Customer(); /** * 如果设置了主键自增长,然后再设置id,就会出现异常: * PersistentObjectException: detached entity passed to persist: com.qingmu.Customer */// customer.setCustId(3L); customer.setCustName("青木堂"); customer.setCustAddress("北京市昌平区"); customer.setCustIndustry("教育"); customer.setCustLevel("VIP"); customer.setCustPhone("12345678912"); customer.setCustSource("网络"); EntityManager entityManager = null; //创建事务 EntityTransaction transaction = null; try { //获取实体类管理对象 entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); //开始事务 transaction.begin(); //创建一个pojo对象 //保存 entityManager.persist(customer); //提交 transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { //关闭资源 entityManager.close(); entityManagerFactory.close(); } } /** * 更新 */ @Test public void update() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer customer = entityManager.find(Customer.class, 2L); customer.setCustName("qingmutang"); transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); entityManagerFactory.close(); } } /** * 删除 */ @Test public void testRemove() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer customer = entityManager.find(Customer.class, 3L); entityManager.remove(customer); transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } } /** * 根据id查询,立即加载 */ @Test public void findById() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer customer = entityManager.find(Customer.class, 2L); System.out.println(customer); transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } } /** * 根据id查询,延迟加载 */ @Test public void findById2() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer reference = entityManager.getReference(Customer.class, 2L); System.out.println(reference); transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } } /** * 查询全部 */ @Test public void findAll() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); String jpql = "from Customer"; Query query = entityManager.createQuery(jpql); List resultList = query.getResultList(); for (Object o : resultList) { System.out.println(o); } transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } } /** * 分页查询 */ @Test public void limit() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); String jpql = "from Customer"; Query query = entityManager.createQuery(jpql); query.setFirstResult(0); query.setMaxResults(2); List resultList = query.getResultList(); for (Object o : resultList) { System.out.println(o); } transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } }/** *通过条件查询 */ @Test public void ByQuery() { EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); String jpql = "from Customer where custName like ?"; Query query = entityManager.createQuery(jpql); query.setParameter(1, "%青木%"); List resultList = query.getResultList(); for (Object o : resultList) { System.out.println(o); } transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } finally { entityManager.close(); } }/** *分类查询 */ @Test public void sortBy(){ EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); String jpql = "from Customer order by custId desc"; Query query = entityManager.createQuery(jpql); List resultList = query.getResultList(); for (Object o : resultList) { System.out.println(o); } transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); }finally { entityManager.close(); } } /** * 统计查询 */ @Test public void count(){ EntityManager entityManager = null; EntityTransaction transaction = null; try { entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); String jpql = "select count(custId) from Customer"; Query query = entityManager.createQuery(jpql); List resultList = query.getResultList(); for (Object o : resultList) { System.out.println(o); } transaction.commit(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); }finally { entityManager.close(); } }}