JPA入門

原文發佈於:http://www.gufeng.tech/  穀風的個人主頁

    JPA全稱Java Persistence API即Java持久化API,是一種通過註解或者XML配置描述映射關係來實現將實體持久化到數據庫的一種java持久化實現方案。JPA和JDBC一樣,都是jdk提供的API,各廠商提供實現,目前的實現有Apache的OpenJPA以及應用廣泛的Hibernate,當然還有其它的實現,這裏就不一一列出了。JAP作爲一種標準,已經獲得了JavaEES容器的支持,同時也仍然可以在JavaSE環境中使用,這就奠定了它可被廣泛應用的前提。


    JPA在隨着SpringBoot的默認支持,再次被廣泛提及、應用。作爲一種ORM的技術,除了擁有ORM的特點之外,還有一些它自己的特點:

1 標準化

JPA是java標準化組織JCP提出的一項持久化標準,所以其任何實現都提供了相同的API,即便更換了實現方案,兼容性也是非常好的。

2 更面向對象

JPA支持面向對象中的繼承、多態及多個類間的關聯關係,因此使得程序員在使用JPA開發時可以方便的使用面向對象的思維,過渡性比較好。

3 功能全面

JPA支持事務、併發等特性,而不僅僅是一個簡單的持久化框架,因而可以在實際使用中發揮更大的作用。

4 卓越的查詢能力

    JPA是面向對象的,定義了JPQL(Java Persistence Query Language),JPQL是一種針對實體的查詢語句,操作對象是實體,可以以面向對象的方式構造查詢語句,在這點上類似Hibernate的HQL。JPQL能夠支持批量操作(如更新和修改)、join、group by、having等子句,同時還支持子查詢,因此其查詢能力可見一斑。

5 集成方便

    這一點從SpringBoot選擇了JPA就能夠看出來。在JPA框架下創建實體只需要使用javax.persistence.Entity註解即可,其接口使用也非常簡單容易上手,尤其重要的一點是JPA被設計成非***式的,天然註定了它能夠被非常容易的集成。


JPA涉及的技術

1 元數據

關於映射關係,JPA同時支持註解和XML。

2 API

操作簡單,將程序員從繁瑣的SQL中解放出來。

3 查詢語言

通過面向對象的方式進行數據查詢,避免程序與SQL語句的的耦合。


    上面提及了JPA的各種好處,那麼作爲一種技術方案(或者叫規範),JPA有沒有缺點呢?答案是肯定的,JPA將數據庫關係以實體及實體間關係表示,必然存在一種將數據庫的複雜概念(如一對一、一對多、多對多等關係)轉移到程序中。這會帶來以下一些問題:

1 程序可讀性差,如果遇到特別複雜的業務邏輯,那麼對於實體的定義也會非常困難,這需要設計者具有非常高的抽象、規範、設計能力。

2 數據關係發生變化時,實體必然也會發生變化。

3 將關係型數據庫映射到面向對象程序上,本身就有着深度的複雜性,兩者關注點不同,當關聯到一起的時候必然會來帶衝突。數據庫關心的是數據以及數據的完整性;面向對象關心的是對象的成員及行爲。


接下來介紹下JPA的一些核心類:

1 EntityManagerFactory

    EntityManagerFactory 是 EntityManager 的工廠類,負責創建 EntityManager 對象。

2 EntityManager

    EntityManager 是 JPA 應用中使用的基本對象,通過它提供的相應方法可以管理持久化對象,也可以新建或者刪除持久化對象。EntityManager 還負責創建 Query 實例。在容器外使用時,EntityManagerFactory 和 EntityManager 之間是一對一的關係。

EntityTransaction

    EntityTransaction 提供 Entity 操作時需要的事務管理,和 EntityManager 是一對一的關係。在查詢操作時不需要使用 EntityTransaction,而在對象持久化、狀態更新、對象刪除等情況下則必須使用顯式的使用 EntityTransaction 的相關方法管理事務。

4 Query

    Query 是查詢實體的接口,Query 對象可以從 EntityManager 中獲得。根據 EJB 3.0 規範中的描述,Query 接口需要同時支持 JPQL 和原生態 SQL 兩種語法。

5 Persistence

    Persistence 是一個工具類,負責根據配置文件提供的參數創建 EntityManagerFactory 對象。


最後看一段JPA的示例代碼:

import javax.persistence.Column;  
import javax.persistence.Entity;  
import javax.persistence.Id;  
import javax.persistence.Table;  
  
@Entity  
@Table(name = "user")  
public class User {  
    @Id  
    @Column(name = "id")  
    private String id;  
  
    @Column(name = "name")  
    private String name;  
  
    public String getId() {  
        return id;  
    }  
  
    public void setId(String id) {  
        this.id = id;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
   
}
import javax.persistence.EntityManager;  
import javax.persistence.EntityManagerFactory;  
import javax.persistence.Persistence;  
import java.util.List;  
  
public class Main {  
    static EntityManagerFactory emf = Persistence.createEntityManagerFactory("gufengJPA");  
    static EntityManager em = emf.createEntityManager();  
  
    public static void main(String[] args) {  
        User person = new User();   
        person.setId(123456l);  
        person.setName("張無忌");  
        em.persist(person);  
  
        add(person);  
  
        System.out.println("user id:" + person.getId());  
        User user = find(person.getId());  
        System.out.println(user);  
  
        List<User> all = findAll();  
        for (User u : all) {  
            System.out.println(u);  
        }  
  
        em.close();  
        emf.close();  
    }  
   
    public static void add(User user) {  
        em.getTransaction().begin();  
        em.persist(user);  
        em.getTransaction().commit();  
    }  
   
    public static User find(Object id) {  
        User user = em.find(User.class, id);  
        return user;  
    }  
  
    public static List<User> findAll() {  
        List<User> users = em.createQuery("select u from User u")  
                .getResultList();  
        return users;  
    }  
}
<?xml version="1.0" encoding="UTF-8"?>  
<persistence version="2.0"  
             xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  
             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">  
    <!-- 持久化單元 -->  
    <persistence-unit name="gufengJPA" transaction-type="RESOURCE_LOCAL">  
        <!--可以指定,如果不指定則從META-INF/services加載-->  
        <!--<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>-->  
        <!-- <class>com.micmiu.hibernate.jpa.UserInfo</class> -->  
        <!--<provider>com.tongweb.openjpa.persistence.PersistenceProviderImpl</provider>-->  
        <!--<jta-data-source>MyDataSource</jta-data-source>-->  
        <!-- class 定義指定持久化的實體類 注意配置屬性hibernate.archive.autodetection=false -->  
        <!--<class>jpa.User</class>-->  
        <properties>  
            <property name="hibernate.archive.autodetection" value="class,hbm"/>  
  
            <!--Hibernate 方言 -->  
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>  
  
            <!--數據庫url -->  
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test"/>  
            <!--數據庫驅動 -->  
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>  
            <!--配置數據庫用戶名 -->  
            <property name="hibernate.connection.username" value="root"/>  
            <!--配置數據庫密碼 -->  
            <property name="hibernate.connection.password" value="123456"/>  
  
            <!--設置外連接抓取樹的最大深度 -->  
            <!--<property name="hibernate.max_fetch_depth" value="3"/>-->  
            <!--自動輸出schema創建DDL語句 -->  
            <!--<property name="hibernate.hbm2ddl.auto" value="update"/>-->  
  
            <property name="hibernate.show_sql" value="true"/>  
  
        </properties>  
    </persistence-unit>  
</persistence>

    這裏需要注意的是JPA配置文件persistence.xml 必需放到類路徑的根路徑的META-INF文件夾下。

   

Persistence.createEntityManagerFactory("gufengJPA");

    上面這行代碼是通過Java的SPI機制獲得具體實現的。在hibernate的jar包裏有個META-INF/services/javax.persistence.spi.PersistenceProvider 文件,這裏指定的實現爲 org.hibernate.jpa.HibernatePersistenceProvider。再有多個的時候,Persistence只會使用第一個。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章