(1)、JPA介紹:
JPA全稱為Java Persistence API ,Java持久化API是Sun公司在Java EE 5規(guī)范中提出的Java持久化接口。JPA吸取了目前Java持久化技術的優(yōu)點,旨在規(guī)范、簡化Java對象的持久化工作。使用JPA持久化對象,并不是依賴于某一個ORM框架。
為什么要使用JAP?
在說為什么要使用JPA之前,我們有必要了解為什么要使用ORM技術。
ORM 是Object-Relation-Mapping,即對象關系影射技術,是對象持久化的核心。ORM是對JDBC的封裝,從而解決了JDBC的各種存在問題:
a) 繁瑣的代碼問題
用JDBC的API編程訪問數據庫,代碼量較大,特別是訪問字段較多的表的時候,代碼顯得繁瑣、累贅,容易出錯。例如:PreparedStatement pstmt=con.prepareStatment("insert into account value(?,?,?,?,?,?,?,?,?)");
ORM則建立了Java對象與數據庫對象之間的影射關系,程序員不需要編寫復雜的SQL語句,直接操作Java對象即可,從而大大降低了代碼量,也使程序員更加專注于業(yè)務邏輯的實現(xiàn)。
b) 數據庫對象連接問題
關系數據對象之間,存在各種關系,包括1對1、1對多、多對1、多對多、級聯(lián)等。在數據庫對象更新的時候,采用JDBC編程,必須十分小心處理這些關系,以保證維持這些關系不會出現(xiàn)錯誤,而這個過程是一個很費時費力的過程。
ORM建立Java對象與數據庫對象關系影射的同時,也自動根據數據庫對象之間的關系創(chuàng)建Java對象的關系,并且提供了維持這些關系完整、有效的機制。
c) 系統(tǒng)架構問題
JDBC屬于數據訪問層,但是使用JDBC編程時,必須知道后臺是用什么數據庫、有哪些表、各個表有有哪些字段、各個字段的類型是什么、表與表之間什么關系、創(chuàng)建了什么索引等等與后臺數據庫相關的詳細信息。
使用ORM技術,可以將數據庫層完全隱蔽,呈獻給程序員的只有Java的對象,程序員只需要根據業(yè)務邏輯的需要調用Java對象的Getter和 Setter方法,即可實現(xiàn)對后臺數據庫的操作,程序員不必知道后臺采用什么數據庫、有哪些表、有什么字段、表與表之間有什么關系。
d) 性能問題
采用JDBC編程,在很多時候存在效率低下的問題。
pstmt =conn.prepareStatement("insert into user_info values(?,?)");
for (int i=0; i<1000; i++) {
pstmt.setInt(1,i);
pstmt.setString(2,"User"+i.toString());
pstmt.executeUpdate();
}
以上程序將向后臺數據庫發(fā)送1000次SQL語句執(zhí)行請求,運行效率較低。
采用ORM技術,ORM框架將根據具體數據庫操作需要,會自動延遲向后臺數據庫發(fā)送SQL請求,ORM也可以根據實際情況,將數據庫訪問操作合成,盡量減少不必要的數據庫操作請求。
JPA是目前比較流行的一種ORM技術之一,所以他擁有ORM技術的各種特點,當然他還有自己的一些優(yōu)勢:
1 標準化
JPA 是 JCP 組織發(fā)布的 Java EE 標準之一,因此任何聲稱符合 JPA 標準的框架都遵循同樣的架構,提供相同的訪問 API,這保證了基于JPA開發(fā)的企業(yè)應用能夠經過少量的修改就能夠在不同的JPA框架下運行。
2 對容器級特性的支持
JPA 框架中支持大數據集、事務、并發(fā)等容器級事務,這使得 JPA 超越了簡單持久化框架的局限,在企業(yè)應用發(fā)揮更大的作用。
3 簡單易用,集成方便
JPA的主要目標之一就是提供更加簡單的編程模型:在JPA框架下創(chuàng)建實體和創(chuàng)建Java 類一樣簡單,沒有任何的約束和限制,只需要使用 javax.persistence.Entity進行注釋;JPA的框架和接口也都非常簡單,沒有太多特別的規(guī)則和設計模式的要求,開發(fā)者可以很容易的掌握。JPA基于非侵入式原則設計,因此可以很容易的和其它框架或者容器集成。
4 可媲美JDBC的查詢能力
JPA的查詢語言是面向對象而非面向數據庫的,它以面向對象的自然語法構造查詢語句,可以看成是Hibernate HQL的等價物。JPA定義了獨特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一種擴展,它是針對實體的一種查詢語言,操作對象是實體,而不是關系數據庫的表,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級查詢特性,甚至還能夠支持子查詢。
5 支持面向對象的高級特性
JPA 中能夠支持面向對象的高級特性,如類之間的繼承、多態(tài)和類之間的復雜關系,這樣的支持能夠讓開發(fā)者最大限度的使用面向對象的模型設計企業(yè)應用,而不需要自行處理這些特性在關系數據庫的持久化。
(2)、具體例子
完成工程后工程結構如下圖:
(注意:persistence.xml文件的位置決定持久性的根(Persistence Root)。持久性的根為JAR文件或者包含META-INF目錄(前提是persistence.xml位于此)的目錄。一般將這個persistence.xml文件放在src下的META-INF中。命名及位置都不能變)
a)、導入相關jar包(見上圖)和創(chuàng)建META-INF和persistence.xml文件.
persistence.xml配置如下:(我用的數據為mysql,采用不同數據庫及JPA的不同實現(xiàn)版本會導致配置內容不同)
- <persistence 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_version=1">
- <persistence-unit name="mysqlJPA" transaction-type="RESOURCE_LOCAL">
- <properties>
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
- <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.connection.url" value="jdbc:mysql://localhost:3306/db1" />
- <property name="hibernate.max_fetch_depth" value="3" />
- <property name="hibernate.hbm2ddl.auto" value="update" />
- </properties>
- </persistence-unit>
- </persistence>
b)、編寫實體bean,如下:
- package com.hmk.bean;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
-
- @Entity
- public class Person {
- private int id;
- private String name;
-
- @Id @GeneratedValue
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- @Column(length=12)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
-
- }
c)、編寫junit測試代碼,如下:
- package junit.test;
-
-
- import javax.persistence.EntityManager;
- import javax.persistence.EntityManagerFactory;
- import javax.persistence.Persistence;
-
- import org.junit.BeforeClass;
- import org.junit.Test;
-
- import com.hmk.bean.Person;
-
- public class JpaTest {
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- }
-
- @Test public void createTable(){
- //可以驗證生成表是否正確
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- factory.close();
- }
-
- @Test public void save(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- em.getTransaction().begin();
- Person person = new Person(); //person為new狀態(tài)
- person.setName("zhang san");
- em.persist(person); //持久化實體
- em.getTransaction().commit();
- em.close();
- factory.close();
- }
- //new 、托管、脫管、刪除
-
- @Test public void update(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- em.getTransaction().begin();
- Person person = em.find(Person.class, 1);
- person.setName("hmk"); //person為托管狀態(tài)
- em.getTransaction().commit();
- em.close();
- factory.close();
- }
-
- @Test public void update2(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- em.getTransaction().begin();
- Person person = em.find(Person.class, 1);
- em.clear(); //把實體管理器中的所有實體變?yōu)槊摴軤顟B(tài)
- person.setName("hmk2");
- em.merge(person); //把脫管狀態(tài)變?yōu)橥泄軤顟B(tài),merge可以自動選擇insert or update 數據
- em.getTransaction().commit();
- em.close();
- factory.close();
- }
-
- @Test public void remove(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- em.getTransaction().begin();
- Person person = em.find(Person.class, 1);
- em.remove(person); //刪除實體
- em.getTransaction().commit();
- em.close();
- factory.close();
- }
-
- @Test public void find(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- Person person = em.find(Person.class, 2); //類似于hibernate的get方法,沒找到數據時,返回null
- System.out.println(person.getName());
- em.close();
- factory.close();
- }
- @Test public void find2(){
- EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysqlJPA");
- EntityManager em = factory.createEntityManager();
- Person person = em.getReference(Person.class, 2); //類似于hibernate的load方法,延遲加載.沒相應數據時會出現(xiàn)異常
- System.out.println(person.getName()); //真正調用時才查找數據
- em.close();
- factory.close();
- }
- }
d)、運行junit測試代碼里的相應方法就行可以。