在講解JPA以前先將hibernate和JPA簡單的瞭解一下.java
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包.
能夠在
http://sourceforge.net/projects/hibernate/files/hibernate-orm/5.0.7.Final/
這裏進行下載.
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 ""; //表示主鍵初始值,默認爲0 int initialValue() default 0; //表示每次主鍵值增長的大小,例如設置1,則表示每次插入新紀錄後自動加1,默認爲50 int 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 @Test String 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(); } } }