一、JPA 入門

Java Persistence API:用于對象持久化的 API
Java EE 5.0 平臺標準的 ORM 規(guī)范,使得應用程序以統(tǒng)一的方式訪問持久層

1. JPA 概述

架構圖:

繪圖1.png

JPA和Hibernate的關系:

JPA 是 hibernate 的一個抽象(就像JDBC和JDBC驅動的關系):

  • JPA 是規(guī)范:JPA 本質上就是一種 ORM 規(guī)范,不是ORM 框架 —— 因為 JPA 并未提供 ORM 實現(xiàn),它只是制訂了一些規(guī)范,提供了一些編程的 API 接口,但具體實現(xiàn)則由 ORM 廠商提供實現(xiàn)

  • Hibernate 是實現(xiàn):Hibernate 除了作為 ORM 框架之外,它也是一種 JPA 實現(xiàn)

  • 從功能上來說, JPA 是 Hibernate 功能的一個子集

JPA 的實現(xiàn)(JPA 供應商):

  • Hibernate:
    JPA 的開發(fā)者就是 Hibernate 和 EJB 的開發(fā)者
    Hibernate 從 3.2 開始兼容 JPA

  • OpenJPA
    OpenJPA 是 Apache 組織提供的開源項目

  • TopLink
    TopLink 以前需要收費,如今開源了,Oracle 公司的項目

JPA 的優(yōu)勢:

  • 標準化: 提供相同的 API,這保證了基于JPA 開發(fā)的企業(yè)應用能夠經(jīng)過少量的修改就能夠在不同的 JPA 框架下運行。

  • 簡單易用,集成方便: JPA 的主要目標之一就是提供更加簡單的編程模型,在 JPA 框架下創(chuàng)建實體和創(chuàng)建 Java 類一樣簡單,只需要使用 javax.persistence.Entity 進行注釋;JPA 的框架和接口也都非常簡單。

  • 可媲美JDBC的查詢能力: JPA的查詢語言是面向對象的,JPA定義了獨特的JPQL,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級查詢特性,甚至還能夠支持子查詢。

  • 支持面向對象的高級特性: JPA 中能夠支持面向對象的高級特性,如類之間的繼承、多態(tài)和類之間的復雜關系,最大限度的使用面向對象的模型

JPA 主要 3 技術(掌握)

  • ORM 映射元數(shù)據(jù):JPA 支持 XML 和 JDK 5.0 注解兩種元數(shù)據(jù)的形式,元數(shù)據(jù)描述對象和表之間的映射關系,框架據(jù)此將實體對象持久化到數(shù)據(jù)庫表中。

  • JPA 的 API:用來操作實體對象,執(zhí)行CRUD操作,框架在后臺完成所有的事情,開發(fā)者從繁瑣的 JDBC和 SQL代碼中解脫出來。

  • 查詢語言(JPQL):這是持久化操作中很重要的一個方面,通過面向對象而非面向數(shù)據(jù)庫的查詢語言查詢數(shù)據(jù),避免程序和具體的 SQL 緊密耦合

2. JPA 持久化對象開發(fā)步驟:

2.1 導入 HIBERNATE JPA 實現(xiàn)(配置 POM 文件)

    <dependencies>
        <!--配置 HIBERNATE JPA 實現(xiàn)包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.2.12.Final</version>
        </dependency>
    </dependencies>

2.2 創(chuàng)建 persistence.xml, 在這個文件中配置持久化單元

注意:persistence.xml 放置于 類路徑下的 META-INF 目錄下,persistence.xml 文件名稱固定

圖片.png

  • 需要配置連接數(shù)據(jù)庫信息
  • 需要指定 JPA 使用哪個持久化的框架以及配置該框架的基本屬性
  • 需要指定持久化的實體類
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <!--persistence-unit 定義持久化單元:
        name 屬性:定義持久化單元名稱
        transaction-type 屬性:定義事務類型,此處為本地事務 RESOURCE_LOCAL-->
    <persistence-unit name="helloJpa" transaction-type="RESOURCE_LOCAL">
       <!-- provider 配置 實現(xiàn) JPA 的 ORM 持久化框架-->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
       <!-- properties 定義連接數(shù)據(jù)庫信息-->
        <properties>
            <!-- jpa中連接數(shù)據(jù)庫 -->
            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@192.168.0.112:1521:XE" />
            <property name="javax.persistence.jdbc.user" value="ZHANGJIAN" />
            <property name="javax.persistence.jdbc.password" value="zhangjian"></property>

            <!-- jpa中配置hibernate基本屬性 -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
          <!--  <property name="hibernate.hbm2ddl.auto" value="update" />-->
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        </properties>
    </persistence-unit>
</persistence>

2.3 創(chuàng)建持久化實體類

package org.zj.jpa.demo.entity;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;

/**
 * Created by ZhangJian on 2018/1/17.
 */
@Entity
@Table(name = "t_order")
public class OrderEntity {
    @Id
    @SequenceGenerator(name="seq_name",sequenceName = "order_seq",allocationSize = 1)
    @GeneratedValue(generator = "seq_name")
    private Long id;
    private String description;
    private BigDecimal totalMoney;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createOrderTime;
    private Integer state;

2.4 測試

package org.zj.jpa.demo.test;

import org.zj.jpa.demo.entity.OrderEntity;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;

/**
 * Created by ZhangJian on 2018/1/17.
 */
public class App {
    public static void main(String[] args) {

        // 創(chuàng)建 EntityManagerFactory 對象 類似于 Hibernate 中 sessionFactory 對象
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("helloJpa");
        // 創(chuàng)建 EntityManager 對象 類似于 Hibernate 中的 Session 對象
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();

        // 持久化實體操作
        OrderEntity order =  new OrderEntity();
        order.setCreateOrderTime(new Timestamp(new Date().getTime()));
        order.setDescription("田雞又肚子疼");
        order.setState(1);
        order.setTotalMoney(new BigDecimal(2000));

        entityManager.persist(order);


        // 提交事務
        entityManager.getTransaction().commit();
        entityManager.close();
        entityManagerFactory.close();

    }
}

3.注解元數(shù)據(jù)介紹

/**
 * Entity 注解: 定義該類為持久化類
 *      name 屬性:定義數(shù)據(jù)庫中的表名 跟 該持久化類進行關聯(lián),可以不配,默認關聯(lián)的以實體類的類名對應的表。
 * Table 注解: 如果數(shù)據(jù)庫中沒有表,使用該注解,定義自動創(chuàng)建表的時候的表名
 *
 * ID 注解 : 定義標識屬性
 * GeneratedValue 注解: 描述主鍵的生成的策略
 *          JPA  使用 GenerationType 該枚舉類型定義了 4 種 生成策略:
 *              AUTO: 底層是否支持自增長或者序列
 *              IDENTITY:必須 數(shù)據(jù)庫支持 自增長策略。 mysql
 *              SEQUENCE:支持序列的數(shù)據(jù)庫,oracle :HIBERNATE_SEQ
 *              TABLE: hibernate 自動創(chuàng)建一個 Table 來保存主鍵值。
 *
 * SequenceGenerator 注解:定義創(chuàng)建序列的規(guī)則
 *
 *
 * Column 注解: 定義對應的表的字段的名稱,約束的規(guī)則(定義長度,唯一....),該注解可以不配,不配默認使用實體屬性名稱作為表的列名稱
 *
 *
 * Temporal 注解:定義表中日期的列采用具體的日期類型。
 *      JPA 使用 TemporalType 該枚舉類型 定義了 3z 中 數(shù)據(jù)庫日期類型:
 *          date:帶年月日
 *          time:帶時分秒
 *          TIMESTAMP:帶年月日時分秒后面的更加精確的時間
 *
 * Transient 注解:指定修飾的屬性,不作為表中的列。忽略該屬性
 */
@Entity
@Table(name = "t_order")
public class OrderModel {

    @Id
    @GeneratedValue(generator = "order_seq")
    @SequenceGenerator(name = "order_seq",sequenceName = "order_seq",allocationSize = 1)
    private Long id;

    private String description;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createOrdTime;
    private Integer state;
    private Double totalMoney;

    @Transient
    private  String noCreateColumn;

4. JPA 常用 API

  • Persistence:JPA 提供的一個獲取 EntityManagerFactory 對象的工具類
    Persistence.createEntityManagerFactory("helloJpa")

  • EntityManagerFactory JPA 應用中只有一份,通過它創(chuàng)建 EntityManager 對象。

  • EntityManager 封裝 CRUD 基本操作,管理 實體對象狀態(tài),一級緩存。
    entityManager.persist(order):沒有主鍵的返回值,該方法的執(zhí)行也會把一個臨時狀態(tài)的 對象轉為受容器管理的 持久化對象。只有在刷新容器或者事務提交的時候,才會發(fā) insert 語句到 數(shù)據(jù)庫。
    entityManager.find(OrderModel.class, 1L):返回的是受容器管理的真實的類型的對象,立即加載。
    entityManager.getReference(OrderModel.class,1l):返回的是受容器管理的真實的類型的對象,懶加載
    更新操作方式1,使用快照更新:OrderModel orderModel = entityManager.find(OrderModel.class, 1L);
    orderModel.setDescription("通過快照更新,沒有顯示的調(diào)用 meger方法");
    更新操作方式2,meger: 傳入?yún)?shù)對象如果是 DO 對象,執(zhí)行完該方法然后是 DO 對象,但是方法執(zhí)行后返回的是 PO 對象。merger 更新的 DO 對象會把更新的數(shù)據(jù)就會覆蓋容器中已經(jīng)存在的要修改的 PO 對象數(shù)據(jù)。merger 的參數(shù)對象是 TO ,就會執(zhí)行 insert 操作。
    entityManager.remove(orderModel):刪除的參數(shù)對象為 PO 對象
    entityManager.createQuery("from OrderModel "):創(chuàng)建 Quqery 接口,需要出入 JPQL 語句。

  • Quqery 接口 API:
    query.getResultList():查詢記錄使用 List 封裝。
    query.getSingleResult(): 查詢當行記錄
    setFirstResult(0): 設置開始下標
    setMaxResults(1):設置抓取記錄條數(shù)
    jpql 帶參數(shù)的查詢支持三種:請看hibernate*

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容