- JPA 教程
- JPA - 首頁
- JPA - 簡介
- JPA - 架構
- JPA - ORM 元件
- JPA - 安裝
- JPA - 實體管理器
- JPA - JPQL
- JPA - 高階對映
- JPA - 實體關係
- JPA - Criteria API
- JPA 有用資源
- JPA 快速指南
- JPA - 有用資源
JPA 快速指南
JPA - 簡介
任何企業應用程式都透過儲存和檢索大量資料來執行資料庫操作。儘管有各種可用的儲存管理技術,但應用程式開發人員通常難以高效地執行資料庫操作。
通常,Java 開發人員使用大量程式碼或使用專有框架來與資料庫互動,而使用 JPA,與資料庫互動的負擔大大減輕。它在物件模型(Java 程式)和關係模型(資料庫程式)之間架起了一座橋樑。
關係模型和物件模型之間的不匹配
關係物件以表格格式表示,而物件模型以物件的互連圖格式表示。在將物件模型從關係資料庫中儲存和檢索時,由於以下原因會發生一些不匹配:
粒度:物件模型比關係模型具有更高的粒度。
子型別:並非所有型別的關係資料庫都支援子型別(意味著繼承)。
標識:與物件模型一樣,關係模型在編寫相等性時不會公開標識。
關聯:關係模型在檢視物件領域模型時無法確定多個關係。
資料導航:物件網路中物件之間的資料導航在兩種模型中是不同的。
什麼是 JPA?
Java 永續性 API 是一組類和方法,用於將大量資料持久地儲存到 Oracle 公司提供的資料庫中。
在哪裡使用 JPA?
為了減少編寫關係物件管理程式碼的負擔,程式設計師遵循“JPA 提供程式”框架,該框架允許輕鬆與資料庫例項互動。此處所需的框架由 JPA 接管。
JPA 歷史
早期版本的 EJB 使用 javax.ejb.EntityBean 介面定義了與業務邏輯層相結合的持久層。
在引入 EJB 3.0 時,持久層被分離並指定為 JPA 1.0(Java 永續性 API)。該 API 的規範於 2006 年 5 月 11 日與 JAVA EE5 的規範一起釋出,使用 JSR 220。
JPA 2.0 於 2009 年 12 月 10 日作為 Java 社群流程 JSR 317 的一部分與 JAVA EE6 的規範一起釋出。
JPA 2.1 於 2013 年 4 月 22 日使用 JSR 338 與 JAVA EE7 的規範一起釋出。
JPA 提供程式
JPA 是一個開源 API,因此 Oracle、Redhat、Eclipse 等各種企業供應商透過在其產品中新增 JPA 永續性特性來提供新產品。其中一些產品包括:
Hibernate、Eclipselink、Toplink、Spring Data JPA 等。
JPA - 架構
Java 永續性 API 是將業務實體作為關係實體儲存的來源。它展示瞭如何將簡單的舊 JAVA 物件 (POJO) 定義為實體,以及如何管理具有關係的實體。
類級別架構
下圖顯示了 JPA 的類級別架構。它顯示了 JPA 的核心類和介面。
下表描述了上述架構中顯示的每個單元。
| 單元 | 描述 |
|---|---|
| EntityManagerFactory | 這是 EntityManager 的工廠類。它建立和管理多個 EntityManager 例項。 |
| EntityManager | 它是一個介面,它管理物件的持久化操作。它像 Query 例項的工廠一樣工作。 |
| 實體 | 實體是持久化物件,儲存為資料庫中的記錄。 |
| EntityTransaction | 它與 EntityManager 具有一對一的關係。對於每個 EntityManager,操作由 EntityTransaction 類維護。 |
| 永續性 | 此類包含用於獲取 EntityManagerFactory 例項的靜態方法。 |
| 查詢 | 此介面由每個 JPA 供應商實現,以獲取滿足條件的關係物件。 |
上述類和介面用於將實體作為記錄儲存到資料庫中。它們透過減少程式設計師為將資料儲存到資料庫中編寫程式碼的工作量來幫助程式設計師,以便他們可以專注於更重要的活動,例如編寫將類與資料庫表對映的程式碼。
JPA 類關係
在上圖架構中,類和介面之間的關係屬於 javax.persistence 包。下圖顯示了它們之間的關係。
EntityManagerFactory 和 EntityManager 之間的關係是一對多。它是一個針對 EntityManager 例項的工廠類。
EntityManager 和 EntityTransaction 之間的關係是一對一。對於每個 EntityManager 操作,都有一個 EntityTransaction 例項。
EntityManager 和 Query 之間的關係是一對多。可以使用一個 EntityManager 例項執行多個查詢。
EntityManager 和 Entity 之間的關係是一對多。一個 EntityManager 例項可以管理多個實體。
JPA - ORM 元件
大多數當代應用程式使用關係資料庫來儲存資料。最近,許多供應商轉向物件資料庫以減輕資料維護的負擔。這意味著物件資料庫或物件關係技術負責儲存、檢索、更新和維護資料。此物件關係技術的核心部分是對映 orm.xml 檔案。由於 xml 不需要編譯,因此我們可以輕鬆地對多個數據源進行更改,而管理工作較少。
物件關係對映
物件關係對映 (ORM) 簡要介紹了什麼是 ORM 及其工作原理。ORM 是一種將資料從物件型別轉換為關係型別並反之亦然的能力。
ORM 的主要功能是將物件與其在資料庫中的資料對映或繫結。對映時,我們必須考慮資料、資料型別及其與自身實體或任何其他表中實體的關係。
高階特性
慣用的永續性:它使您可以使用面向物件的類來編寫永續性類。
高效能:它具有許多獲取技術和樂觀的鎖定技術。
可靠性:它非常穩定,被許多專業程式設計師使用。
ORM 架構
ORM 架構如下所示。
上述架構解釋瞭如何在三個階段將物件資料儲存到關係資料庫中。
階段 1
第一階段,稱為物件資料階段,包含 POJO 類、服務介面和類。它是主要的業務元件層,具有業務邏輯操作和屬性。
例如,讓我們以員工資料庫為模式。
Employee POJO 類包含 ID、姓名、工資和職位等屬性。它還包含這些屬性的 setter 和 getter 方法。
Employee DAO/Service 類包含服務方法,例如建立員工、查詢員工和刪除員工。
階段 2
第二階段,稱為對映或永續性階段,包含 JPA 提供程式、對映檔案 (ORM.xml)、JPA 載入程式和物件網格。
JPA 提供程式:它是包含 JPA 特性 (javax.persistence) 的供應商產品。例如 Eclipselink、Toplink、Hibernate 等。
對映檔案:對映檔案 (ORM.xml) 包含 POJO 類中的資料和關係資料庫中的資料之間的對映配置。
JPA 載入程式:JPA 載入程式像快取記憶體一樣工作。它可以載入關係網格資料。它就像資料庫的副本,可以與服務類互動以獲取 POJO 資料(POJO 類的屬性)。
物件網格:它是一個臨時位置,可以儲存關係資料的副本,就像快取記憶體一樣。所有針對資料庫的查詢首先都會對物件網格中的資料起作用。只有在提交後,它才會影響主資料庫。
階段 3
第三階段是關係資料階段。它包含與業務元件邏輯連線的關係資料。如上所述,只有當業務元件提交資料時,它才會物理地儲存到資料庫中。在此之前,修改後的資料將以網格格式儲存在快取記憶體中。獲取資料的過程與儲存資料的過程相同。
上述三個階段的程式設計互動機制稱為物件關係對映。
Mapping.xml
mapping.xml 檔案用於指示 JPA 提供程式將實體類與資料庫表對映。
讓我們以包含四個屬性的 Employee 實體為例。名為Employee.java的 Employee 實體 POJO 類如下所示
public class Employee
{
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
}
以上程式碼是 Employee 實體 POJO 類。它包含四個屬性eid、ename、salary和deg。將這些屬性視為表中的表字段,並將eid視為該表的主鍵。現在我們必須為此設計 hibernate 對映檔案。名為mapping.xml的對映檔案如下所示
<? xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
version="1.0">
<description> XML Mapping file</description>
<entity class="Employee">
<table name="EMPLOYEETABLE"/>
<attributes>
<id name="eid">
<generated-value strategy="TABLE"/>
</id>
<basic name="ename">
<column name="EMP_NAME" length="100"/>
</basic>
<basic name="salary">
</basic>
<basic name="deg">
</basic>
</attributes>
</entity>
</entity-mappings>
上述指令碼用於將實體類與資料庫表對映。在此檔案中
<entity-mappings>:標記定義架構定義,以允許將實體標記新增到 xml 檔案中。
<description>:標記提供有關應用程式的描述。
<entity>:標記定義要轉換為資料庫中表的實體類。class 屬性定義 POJO 實體類名。
<table>:標記定義表名。如果希望類名和表名相同,則不需要此標記。
<attributes>:標記定義屬性(表中的欄位)。
<id>:標記定義表的主鍵。<generated-value>標記定義如何分配主鍵值,例如自動、手動或從序列中獲取。
<basic>:標記用於定義表的其餘屬性。
<column-name>:標記用於定義表中使用者定義的表字段名。
註解
通常,xml 檔案用於配置特定元件或對映兩個不同規格的元件。在我們的例子中,我們必須在框架中分別維護 xml 檔案。這意味著在編寫對映 xml 檔案時,我們需要將 POJO 類屬性與 mapping.xml 檔案中的實體標記進行比較。
這是一個解決方案。在類定義中,我們可以使用註解來編寫配置部分。註解用於類、屬性和方法。註解以“@”符號開頭。註解宣告在類、屬性或方法之前。JPA 的所有註解都定義在javax.persistence包中。
以下是我們在示例中使用的註解列表。
| 註解 | 描述 |
|---|---|
| @Entity | 將類宣告為實體或表。 |
| @Table | 宣告表名。 |
| @Basic | 顯式指定非約束欄位。 |
| @Embedded | 指定其值為可嵌入類的例項的類或實體的屬性。 |
| @Id | 指定屬性,用於類的標識(表的主鍵)。 |
| @GeneratedValue | 指定標識屬性的初始化方式,例如自動、手動或從序列表中獲取值。 |
| @Transient | 指定非持久化屬性,即值永遠不會儲存到資料庫中。 |
| @Column | 指定持久化屬性的列屬性。 |
| @SequenceGenerator | 指定在 @GeneratedValue 註解中指定的屬性的值。它建立一個序列。 |
| @TableGenerator | 指定在 @GeneratedValue 註解中指定的屬性的值生成器。它建立一個用於值生成的表。 |
| @AccessType | 此型別的註解用於設定訪問型別。如果設定 @AccessType(FIELD),則訪問方式為欄位級。如果設定 @AccessType(PROPERTY),則訪問方式為屬性級。 |
| @JoinColumn | 指定實體關聯或實體集合。這用於多對一和一對多關聯。 |
| @UniqueConstraint | 指定主鍵表或輔助表的欄位和唯一約束。 |
| @ColumnResult | 使用 select 子句引用 SQL 查詢中列的名稱。 |
| @ManyToMany | 定義連線表之間的多對多關係。 |
| @ManyToOne | 定義連線表之間的多對一關係。 |
| @OneToMany | 定義連線表之間的一對多關係。 |
| @OneToOne | 定義連線表之間的一對一關係。 |
| @NamedQueries | 指定命名查詢列表。 |
| @NamedQuery | 使用靜態名稱指定查詢。 |
Java Bean 標準
Java 類將例項值及其行為封裝到稱為物件的單個單元中。Java Bean 是一個臨時儲存和可重用的元件或物件。它是一個可序列化的類,具有預設建構函式和 getter 和 setter 方法,用於分別初始化例項屬性。
Bean 約定
Bean 包含其預設建構函式或包含序列化例項的檔案。因此,一個 Bean 可以例項化另一個 Bean。
Bean 的屬性可以分為布林屬性和非布林屬性。
非布林屬性包含 **getter** 和 **setter** 方法。
布林屬性包含 **setter** 和 **is** 方法。
任何屬性的 **getter** 方法都應以小寫的 **get** 開頭(Java 方法約定),然後繼續使用以大寫字母開頭的欄位名稱。例如,欄位名稱為 **salary**,因此該欄位的 getter 方法為 **getSalary ()**。
任何屬性的 **setter** 方法都應以小寫的 **set** 開頭(Java 方法約定),然後繼續使用以大寫字母開頭的欄位名稱和要設定為欄位的 **引數值**。例如,欄位名稱為 **salary**,因此該欄位的 setter 方法為 **setSalary (double sal)**。
對於布林屬性,**is** 方法用於檢查其真假。例如,布林屬性 **empty**,該欄位的 **is** 方法為 **isEmpty ()**。
JPA - 安裝
本章將引導您完成在基於 Windows 和 Linux 的系統上設定 JPA 的過程。只需幾個簡單的步驟,即可輕鬆安裝 JPA 並將其與您當前的 Java 環境整合,無需任何複雜的設定過程。安裝過程中需要使用者管理。
系統要求
| JDK | Java SE 2 JDK 1.5 或更高版本 |
| 記憶體 | 1 GB RAM(推薦) |
| 磁碟空間 | 無最低要求 |
| 作業系統版本 | Windows XP 或更高版本,Linux |
現在讓我們繼續進行安裝 JPA 的步驟。
步驟 1:驗證您的 Java 安裝
首先,您需要在系統上安裝 Java 軟體開發工具包 (SDK)。要驗證這一點,請根據您正在使用的平臺執行以下兩個命令中的任何一個。
如果 Java 安裝已正確完成,則它將顯示您 Java 安裝的當前版本和規範。示例輸出如下表所示。
| 平臺 | 命令 | 示例輸出 |
|---|---|---|
| Windows | 開啟命令控制檯並輸入 >java –version |
Java version "1.7.0_60" Java (TM) SE Run Time Environment (build 1.7.0_60-b19) Java Hotspot (TM) 64-bit Server VM (build 24.60-b09, mixed mode) |
| Linux | 開啟命令終端並輸入 $java –version |
java version "1.7.0_25" Open JDK Runtime Environment (rhel-2.3.10.4.el6_4-x86_64) Open JDK 64-Bit Server VM (build 23.7-b01, mixed mode) |
我們假設本教程的讀者在他們的系統上安裝了 Java SDK 版本 1.7.0_60。
如果您沒有 Java SDK,請從此處下載其當前版本:[http://www.oracle.com/technetwork/java/javase/downloads/index.html](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 並安裝它。
步驟 2:設定您的 Java 環境
設定環境變數 JAVA_HOME 以指向 Java 安裝在您計算機上的基目錄位置。例如:
| 平臺 | 描述 |
|---|---|
| Windows | 將 JAVA_HOME 設定為 C:\ProgramFiles\java\jdk1.7.0_60 |
| Linux | export JAVA_HOME=/usr/local/java-current |
將 Java 編譯器位置的完整路徑附加到系統路徑。
| 平臺 | 描述 |
|---|---|
| Windows | 將字串“C:\Program Files\Java\jdk1.7.0_60\bin”附加到系統變數 PATH 的末尾。 |
| Linux | export PATH=$PATH:$JAVA_HOME/bin/ |
從命令提示符執行命令 **java -version**,如上所述。
步驟 3:安裝 JPA
您可以透過使用本教程中的任何 JPA 提供程式來完成 JPA 安裝,例如 EclipseLink、Hibernate。讓我們按照使用 EclipseLink 安裝 JPA 的方法進行操作。對於 JPA 程式設計,我們需要遵循特定的資料夾框架,因此最好使用 IDE。
從以下連結下載 Eclipse IDE:[https://www.eclipse.org/downloads/](https://www.eclipse.org/downloads/) 選擇用於 Java EE 開發人員的 Eclipse IDE,即 **Eclipse indigo**。
將 Eclipse zip 檔案解壓縮到 C 盤。開啟 Eclipse IDE。
使用 EclipseLink 安裝 JPA
EclipseLink 是一個庫,因此我們無法將其直接新增到 Eclipse IDE 中。要使用 EclipseLink 安裝 JPA,您需要按照以下步驟操作。
透過在 Eclipse IDE 中選擇 **檔案 -> 新建 -> JPA 專案** 來建立一個新的 JPA 專案,如下所示

您將獲得一個名為 **新建 JPA 專案** 的對話方塊。輸入專案名稱 **tutorialspoint_JPA_Eclipselink**,檢查 **jre** 版本並單擊下一步

在使用者庫部分單擊下載庫(如果您沒有該庫)。

在下載庫對話方塊中選擇最新版本的 EclipseLink 庫,然後單擊下一步,如下所示

接受許可證條款並單擊完成以下載庫。

6. 下載開始,如下圖所示。

下載完成後,在使用者庫部分選擇下載的庫,然後單擊完成。

最後,您將在 Eclipse IDE 的 **包資源管理器** 中獲得專案檔案。解壓縮所有檔案,您將獲得如下所示的資料夾和檔案層次結構

將 MySQL 聯結器新增到專案
我們在此處討論的任何示例都需要資料庫連線。讓我們考慮使用 MySQL 資料庫進行資料庫操作。它需要 mysql-connector jar 來與 Java 程式互動。
按照以下步驟在專案中配置資料庫 jar。
透過右鍵單擊專案轉到專案屬性 **->** Java 構建路徑。您將獲得如下螢幕截圖所示的對話方塊。單擊新增外部 Jar。

轉到系統記憶體中的 jar 位置,選擇檔案並單擊開啟。

單擊屬性對話方塊上的確定。您將獲得專案中的 MySQL-connector Jar。現在您可以使用 MySQL 進行資料庫操作了。
JPA - 實體管理器
本章使用一個簡單的示例來演示 JPA 的工作原理。讓我們考慮員工管理為例。假設員工管理建立、更新、查詢和刪除員工記錄。如前所述,我們使用 MySQL 資料庫進行資料庫操作。
此示例的主要模組如下所示
模型或 POJO
Employee.java
永續性
persistence.xml
服務
CreatingEmployee.java
UpdatingEmployee.java
FindingEmployee.java
DeletingEmployee.java
讓我們採用我們在使用 EclipseLink 進行 JPA 安裝時使用的包層次結構。按照如下所示的層次結構進行此示例
建立實體
實體不過是 Bean 或模型。在此示例中,我們將使用 **Employee** 作為實體。**eid**、**ename**、**salary** 和 **deg** 是此實體的屬性。它包含一個預設建構函式以及這些屬性的 setter 和 getter 方法。
在上圖所示的層次結構中,在 **src**(源)包下建立一個名為 **'com.tutorialspoint.eclipselink.entity'** 的包。如下所示,在給定包下建立一個名為 **Employee.java** 的類
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table
public class Employee
{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
@Override
public String toString() {
return "Employee [eid=" + eid + ", ename=" + ename + ", salary="
+ salary + ", deg=" + deg + "]";
}
}
在上面的程式碼中,我們使用了 @Entity 註解來使這個 POJO 類成為一個實體。
在進入下一個模組之前,我們需要為關係實體建立資料庫,這將把資料庫註冊到 **persistence.xml** 檔案中。開啟 MySQL Workbench 並輸入以下查詢。
create database jpadb use jpadb
persistence.xml
此模組在 JPA 的概念中起著至關重要的作用。在這個 xml 檔案中,我們將註冊資料庫並指定實體類。
在上圖所示的包層次結構中,JPA 內容包下的 persistence.xml 如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
在上面的 xml 中,**<persistence-unit>** 標籤用 JPA 永續性的特定名稱定義。**<class>** 標籤使用包名稱定義實體類。**<properties>** 標籤定義所有屬性,**<property>** 標籤定義每個屬性,例如資料庫註冊、URL 指定、使用者名稱和密碼。這些是 EclipseLink 屬性。此檔案將配置資料庫。
持久化操作
持久化操作用於與資料庫互動,它們是 **載入** 和 **儲存** 操作。在業務元件中,所有持久化操作都屬於服務類。
在上圖所示的包層次結構中,在 **src**(源)包下建立一個名為 **'com.tutorialspoint.eclipselink.service'** 的包。所有名為 CreateEmloyee.java、UpdateEmployee.java、FindEmployee.java 和 DeleteEmployee.java 的服務類都位於給定包下,如下所示
建立員工
以下程式碼段顯示瞭如何建立一個名為 **CreateEmployee.java** 的 Employee 類。
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Employee;
public class CreateEmployee
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
Employee employee = new Employee( );
employee.setEid( 1201 );
employee.setEname( "Gopal" );
employee.setSalary( 40000 );
employee.setDeg( "Technical Manager" );
entitymanager.persist( employee );
entitymanager.getTransaction( ).commit( );
entitymanager.close( );
emfactory.close( );
}
}
在上面的程式碼中,**createEntityManagerFactory ()** 透過提供與我們在 persistent.xml 檔案中為 persistence-unit 提供的相同唯一名稱來建立一個永續性單元。**entitymanagerfactory** 物件將使用 **createEntityManager ()** 方法建立 **entitymanger** 例項。**entitymanager** 物件為事務管理建立 **entitytransaction** 例項。透過使用 **entitymanager** 物件,我們可以將實體持久化到資料庫中。
編譯並執行上述程式後,您將在 Eclipse IDE 的控制面板上收到來自 EclipseLink 庫的通知。
對於結果,開啟 MySQL Workbench 並鍵入以下查詢。
use jpadb select * from employee
受影響的資料庫表名為 **employee**,將以表格格式顯示如下
| Eid | Ename | Salary | Deg |
|---|---|---|---|
| 1201 | Gopal | 40000 | 技術經理 |
更新員工
要更新員工的記錄,我們需要從資料庫中檢索現有記錄,進行更改,最後將其提交到資料庫。名為 **UpdateEmployee.java** 的類如下所示
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Employee;
public class UpdateEmployee
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
Employee employee=entitymanager.
find( Employee.class, 1201 );
//before update
System.out.println( employee );
employee.setSalary( 46000 );
entitymanager.getTransaction( ).commit( );
//after update
System.out.println( employee );
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制面板上收到來自 EclipseLink 庫的通知。
對於結果,開啟 MySQL Workbench 並鍵入以下查詢。
use jpadb select * from employee
受影響的資料庫表名為 **employee**,將以表格格式顯示如下
| Eid | Ename | Salary | Deg |
|---|---|---|---|
| 1201 | Gopal | 46000 | 技術經理 |
員工 1201 的薪水已更新為 46000。
查詢員工
要查詢員工的記錄,我們將不得不從資料庫中檢索現有資料並將其顯示出來。在此操作中,在檢索記錄時不應用 EntityTransaction。
名為 **FindEmployee.java** 的類如下所示。
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Employee;
public class FindEmployee
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence
.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager();
Employee employee = entitymanager.
find( Employee.class, 1201 );
System.out.println("employee ID = "+employee.getEid( ));
System.out.println("employee NAME = "+employee.getEname( ));
System.out.println("employee SALARY = "+employee.getSalary( ));
System.out.println("employee DESIGNATION = "+employee.getDeg( ));
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制面板上收到來自 EclipseLink 庫的以下輸出。
employee ID = 1201 employee NAME = Gopal employee SALARY = 46000.0 employee DESIGNATION = Technical Manager
刪除員工
要刪除員工的記錄,我們首先將查詢現有記錄,然後將其刪除。這裡 EntityTransaction 起著重要的作用。
名為 **DeleteEmployee.java** 的類如下所示
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Employee;
public class DeleteEmployee
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
Employee employee=entitymanager.
find( Employee.class, 1201 );
entitymanager.remove( employee );
entitymanager.getTransaction( ).commit( );
entitymanager.close( );
emfactory.close( );
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制面板上收到來自 EclipseLink 庫的通知。
對於結果,開啟 MySQL Workbench 並鍵入以下查詢。
use jpadb select * from employee
受影響的資料庫名為 **employee** 將包含空記錄。
完成本示例中所有模組後,包和檔案層次結構如下所示
JPA - JPQL
本章介紹 JPQL 及其與持久化單元的協同工作方式。本章中給出的示例遵循與上一章相同的包層次結構。
Java 持久化查詢語言
JPQL 代表 Java 持久化查詢語言 (Java Persistence Query Language)。它用於建立針對實體的查詢,以將資料儲存到關係資料庫中。JPQL 基於 SQL 語法開發。但它不會直接影響資料庫。
JPQL 可以使用 SELECT 語句檢索資料,可以使用 UPDATE 語句和 DELETE 語句進行批次更新。
查詢結構
JPQL 語法與 SQL 語法非常相似。具有類似 SQL 的語法是一個優勢,因為 SQL 簡單且廣泛使用。SQL 直接針對關係資料庫表、記錄和欄位,而 JPQL 則與 Java 類和例項一起使用。
例如,JPQL 查詢可以檢索實體物件,而不是像 SQL 那樣從資料庫檢索欄位結果集。JPQL 查詢結構如下所示。
SELECT ... FROM ... [WHERE ...] [GROUP BY ... [HAVING ...]] [ORDER BY ...]
JPQL DELETE 和 UPDATE 查詢的結構如下所示。
DELETE FROM ... [WHERE ...] UPDATE ... SET ... [WHERE ...]
標量和聚合函式
標量函式根據輸入值返回結果值。聚合函式透過計算輸入值來返回結果值。
我們將使用與上一章相同的員工管理示例。在這裡,我們將使用 JPQL 的標量和聚合函式來介紹服務類。
讓我們假設 **jpadb.employee** 表包含以下記錄。
| Eid | Ename | Salary | Deg |
|---|---|---|---|
| 1201 | Gopal | 40000 | 技術經理 |
| 1202 | Manisha | 40000 | 校對員 |
| 1203 | Masthanvali | 40000 | 技術撰稿人 |
| 1204 | Satish | 30000 | 技術撰稿人 |
| 1205 | Krishna | 30000 | 技術撰稿人 |
| 1206 | Kiran | 35000 | 校對員 |
建立一個名為 **ScalarandAggregateFunctions.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,內容如下所示。
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class ScalarandAggregateFunctions
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager();
//Scalar function
Query query = entitymanager.
createQuery("Select UPPER(e.ename) from Employee e");
List<String> list=query.getResultList();
for(String e:list)
{
System.out.println("Employee NAME :"+e);
}
//Aggregate function
Query query1 = entitymanager.
createQuery("Select MAX(e.salary) from Employee e");
Double result=(Double) query1.getSingleResult();
System.out.println("Max Employee Salary :"+result);
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上獲得以下輸出。
Employee NAME :GOPAL Employee NAME :MANISHA Employee NAME :MASTHANVALI Employee NAME :SATISH Employee NAME :KRISHNA Employee NAME :KIRAN ax Employee Salary :40000.0
Between、And、Like 關鍵字
**Between**、**And** 和 **Like** 是 JPQL 的主要關鍵字。這些關鍵字用於查詢中的 **Where 子句** 之後。
建立一個名為 **BetweenAndLikeFunctions.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,內容如下所示。
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class BetweenAndLikeFunctions
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager();
//Between
Query query = entitymanager.
createQuery( "Select e " +
"from Employee e " +
"where e.salary " +
"Between 30000 and 40000" )
List<Employee> list=(List<Employee>)query.getResultList( );
for( Employee e:list )
{
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee salary :"+e.getSalary( ));
}
//Like
Query query1 = entitymanager.
createQuery("Select e " +
"from Employee e " +
"where e.ename LIKE 'M%'");
List<Employee> list1=(List<Employee>)query1.getResultList( );
for( Employee e:list1 )
{
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee name :"+e.getEname( ));
}
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上獲得以下輸出。
Employee ID :1201 Employee salary :40000.0 Employee ID :1202 Employee salary :40000.0 Employee ID :1203 Employee salary :40000.0 Employee ID :1204 Employee salary :30000.0 Employee ID :1205 Employee salary :30000.0 Employee ID :1206 Employee salary :35000.0 Employee ID :1202 Employee name :Manisha Employee ID :1203 Employee name :Masthanvali
排序
要在 JPQL 中對記錄進行排序,我們使用 ORDER BY 子句。此子句的用法與 SQL 中相同,但它處理的是實體。以下示例演示如何使用 ORDER BY 子句。
建立一個名為 **Ordering.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,內容如下所示。
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class Ordering
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager();
//Between
Query query = entitymanager.
createQuery( "Select e " +
"from Employee e " +
"ORDER BY e.ename ASC" );
List<Employee> list=(List<Employee>)query.getResultList( );
for( Employee e:list )
{
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee Name :"+e.getEname( ));
}
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上獲得以下輸出。
Employee ID :1201 Employee Name :Gopal Employee ID :1206 Employee Name :Kiran Employee ID :1205 Employee Name :Krishna Employee ID :1202 Employee Name :Manisha Employee ID :1203 Employee Name :Masthanvali Employee ID :1204 Employee Name :Satish
命名查詢
@NamedQuery 註解定義為具有預定義查詢字串的查詢,該字串不可更改。與動態查詢相比,命名查詢可以透過將 JPQL 查詢字串與 POJO 分離來改進程式碼組織。它還會傳遞查詢引數,而不是將文字動態嵌入到查詢字串中,因此可以生成更高效的查詢。
首先,將 @NamedQuery 註解新增到位於 **com.tutorialspoint.eclipselink.entity** 包下的名為 **Employee.java** 的 Employee 實體類中,內容如下所示。
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table
@NamedQuery(query = "Select e from Employee e where e.eid = :id",
name = "find employee by id")
public class Employee
{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
@Override
public String toString() {
return "Employee [eid=" + eid + ", ename=" + ename + ", salary="
+ salary + ", deg=" + deg + "]";
}
}
建立一個名為 **NamedQueries.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,內容如下所示。
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class NamedQueries
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager();
Query query = entitymanager.createNamedQuery(
"find employee by id");
query.setParameter("id", 1204);
List<Employee> list = query.getResultList( );
for( Employee e:list )
{
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee Name :"+e.getEname( ));
}
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上獲得以下輸出。
Employee ID :1204 Employee Name :Satish
新增所有上述類後,包層次結構如下所示
急切載入和延遲載入
JPA 最重要的概念是在快取記憶體中建立資料庫的副本。在與資料庫進行事務處理時,JPA 首先建立一組重複的資料,只有當使用實體管理器提交時,更改才會影響到資料庫。
有兩種從資料庫中提取記錄的方法。
急切載入
在急切載入中,在提取特定記錄時會自動上傳相關的子物件。
延遲載入
在延遲載入中,除非您專門請求,否則不會自動上傳相關物件。首先,它檢查相關物件的可訪問性併發出通知。稍後,如果您呼叫該實體的任何 getter 方法,它將提取所有記錄。
當您第一次嘗試提取記錄時,延遲載入是可能的。這樣,整個記錄的副本已經儲存在快取記憶體中。從效能方面來看,延遲載入更可取。
JPA - 高階對映
JPA 是一個隨 Java 規範釋出的庫。因此,它支援所有面向物件的實體持久化概念。到目前為止,我們已經完成了物件關係對映的基礎知識。本章將帶您瞭解物件和關係實體之間的高階對映。
繼承策略
繼承是任何面嚮物件語言的核心概念,因此我們可以在實體之間使用繼承關係或策略。JPA 支援三種類型的繼承策略:SINGLE_TABLE、JOINED_TABLE 和 TABLE_PER_CONCRETE_CLASS。
讓我們考慮一個示例。下圖顯示了三個類,即 Staff、TeachingStaff 和 NonTeachingStaff,以及它們之間的關係。
在上圖中,Staff 是一個實體,而 TeachingStaff 和 NonTeachingStaff 是 Staff 的子實體。我們將使用上述示例來演示所有三種繼承策略。
單表策略
單表策略採用所有類的欄位(超類和子類)並將它們對映到一個名為 SINGLE_TABLE 的單表中。在此,鑑別器值在區分單表中三個實體的值方面起著關鍵作用。
讓我們考慮上述示例。TeachingStaff 和 NonTeachingStaff 是 Staff 的子類。根據繼承的概念,子類繼承其超類的屬性。因此,sid 和 sname 是屬於 TeachingStaff 和 NonTeachingStaff 的欄位。建立一個 JPA 專案。該專案的所有模組如下所示
建立實體
在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.entity’** 的包。在給定包下建立一個名為 **Staff.java** 的新 Java 類。Staff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.io.Serializable;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name="type" )
public class Staff implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private int sid;
private String sname;
public Staff( int sid, String sname )
{
super( );
this.sid = sid;
this.sname = sname;
}
public Staff( )
{
super( );
}
public int getSid( )
{
return sid;
}
public void setSid( int sid )
{
this.sid = sid;
}
public String getSname( )
{
return sname;
}
public void setSname( String sname )
{
this.sname = sname;
}
}
在上面的程式碼中,**@DescriminatorColumn** 指定欄位名稱 **(type)**,其值顯示其餘 (Teaching 和 NonTeachingStaff) 欄位。
為 Staff 類建立一個子類 (class),名為 **TeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。TeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue( value="TS" )
public class TeachingStaff extends Staff
{
private String qualification;
private String subjectexpertise;
public TeachingStaff( int sid, String sname,
String qualification,String subjectexpertise )
{
super( sid, sname );
this.qualification = qualification;
this.subjectexpertise = subjectexpertise;
}
public TeachingStaff( )
{
super( );
}
public String getQualification( )
{
return qualification;
}
public void setQualification( String qualification )
{
this.qualification = qualification;
}
public String getSubjectexpertise( )
{
return subjectexpertise;
}
public void setSubjectexpertise( String subjectexpertise )
{
this.subjectexpertise = subjectexpertise;
}
}
為 Staff 類建立一個子類 (class),名為 **NonTeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。NonTeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue( value = "NS" )
public class NonTeachingStaff extends Staff
{
private String areaexpertise;
public NonTeachingStaff( int sid, String sname,
String areaexpertise )
{
super( sid, sname );
this.areaexpertise = areaexpertise;
}
public NonTeachingStaff( )
{
super( );
}
public String getAreaexpertise( )
{
return areaexpertise;
}
public void setAreaexpertise( String areaexpertise )
{
this.areaexpertise = areaexpertise;
}
}
persistence.xml
persistence.xml 包含資料庫的配置資訊和實體類的註冊資訊。xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Staff</class>
<class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
<class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
服務類是業務元件的實現部分。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。
在給定包下建立一個名為 **SaveClient.java** 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類欄位。SaveClient 類如下所示
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;
public class SaveClient
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Teaching staff entity
TeachingStaff ts1=new TeachingStaff(
1,"Gopal","MSc MEd","Maths");
TeachingStaff ts2=new TeachingStaff(
2, "Manisha", "BSc BEd", "English");
//Non-Teaching Staff entity
NonTeachingStaff nts1=new NonTeachingStaff(
3, "Satish", "Accounts");
NonTeachingStaff nts2=new NonTeachingStaff(
4, "Krishna", "Office Admin");
//storing all entities
entitymanager.persist(ts1);
entitymanager.persist(ts2);
entitymanager.persist(nts1);
entitymanager.persist(nts2);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。檢查 MySQL 工作臺以檢視輸出。表格格式的輸出如下所示
| Sid | Type | Sname | Areaexpertise | Qualification | Subjectexpertise |
|---|---|---|---|---|---|
| 1 | TS | Gopal | MSC MED | Maths | |
| 2 | TS | Manisha | BSC BED | English | |
| 3 | NS | Satish | Accounts | ||
| 4 | NS | Krishna | Office Admin |
最終,您將獲得一個包含所有三個類的欄位以及名為 **Type** (欄位) 的鑑別器列的單表。
連線表策略
連線表策略是共享包含唯一值的引用列以連線表並簡化事務。讓我們考慮與上面相同的示例。
建立一個 JPA 專案。所有專案模組如下所示。
建立實體
在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.entity’** 的包。在給定包下建立一個名為 **Staff.java** 的新 Java 類。Staff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table
@Inheritance( strategy = InheritanceType.JOINED )
public class Staff implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private int sid;
private String sname;
public Staff( int sid, String sname )
{
super( );
this.sid = sid;
this.sname = sname;
}
public Staff( )
{
super( );
}
public int getSid( )
{
return sid;
}
public void setSid( int sid )
{
this.sid = sid;
}
public String getSname( )
{
return sname;
}
public void setSname( String sname )
{
this.sname = sname;
}
}
為 Staff 類建立一個子類 (class),名為 **TeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。TeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@PrimaryKeyJoinColumn(referencedColumnName="sid")
public class TeachingStaff extends Staff
{
private String qualification;
private String subjectexpertise;
public TeachingStaff( int sid, String sname,
String qualification,String subjectexpertise )
{
super( sid, sname );
this.qualification = qualification;
this.subjectexpertise = subjectexpertise;
}
public TeachingStaff( )
{
super( );
}
public String getQualification( )
{
return qualification;
}
public void setQualification( String qualification )
{
this.qualification = qualification;
}
public String getSubjectexpertise( )
{
return subjectexpertise;
}
public void setSubjectexpertise( String subjectexpertise )
{
this.subjectexpertise = subjectexpertise;
}
}
為 Staff 類建立一個子類 (class),名為 **NonTeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。NonTeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@PrimaryKeyJoinColumn(referencedColumnName="sid")
public class NonTeachingStaff extends Staff
{
private String areaexpertise;
public NonTeachingStaff( int sid, String sname,
String areaexpertise )
{
super( sid, sname );
this.areaexpertise = areaexpertise;
}
public NonTeachingStaff( )
{
super( );
}
public String getAreaexpertise( )
{
return areaexpertise;
}
public void setAreaexpertise( String areaexpertise )
{
this.areaexpertise = areaexpertise;
}
}
persistence.xml
persistence.xml 檔案包含資料庫的配置資訊和實體類的註冊資訊。xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Staff</class>
<class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
<class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
服務類是業務元件的實現部分。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。
在給定包下建立一個名為 **SaveClient.java** 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類欄位。然後,SaveClient 類如下所示
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;
public class SaveClient
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Teaching staff entity
TeachingStaff ts1=new TeachingStaff(
1,"Gopal","MSc MEd","Maths");
TeachingStaff ts2=new TeachingStaff(
2, "Manisha", "BSc BEd", "English");
//Non-Teaching Staff entity
NonTeachingStaff nts1=new NonTeachingStaff(
3, "Satish", "Accounts");
NonTeachingStaff nts2=new NonTeachingStaff(
4, "Krishna", "Office Admin");
//storing all entities
entitymanager.persist(ts1);
entitymanager.persist(ts2);
entitymanager.persist(nts1);
entitymanager.persist(nts2);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。有關輸出,請檢查 MySQL 工作臺。
這裡建立了三個表,並在表格格式中顯示了 **staff** 表的結果。
| Sid | Dtype | Sname |
|---|---|---|
| 1 | TeachingStaff | Gopal |
| 2 | TeachingStaff | Manisha |
| 3 | NonTeachingStaff | Satish |
| 4 | NonTeachingStaff | Krishna |
**TeachingStaff** 表的結果如下所示
| Sid | Qualification | Subjectexpertise |
|---|---|---|
| 1 | MSC MED | Maths |
| 2 | BSC BED | English |
在上表中,sid 是外部索引鍵(來自 staff 表的引用欄位)。**NonTeachingStaff** 表的結果如下所示
| Sid | Areaexpertise |
|---|---|
| 3 | Accounts |
| 4 | Office Admin |
最後,使用各自的欄位建立三個表,並且 SID 欄位由所有三個表共享。在 Staff 表中,SID 是主鍵。在其餘兩個表(TeachingStaff 和 NonTeachingStaff)中,SID 是外部索引鍵。
每個類一個表策略
每個類一個表策略是為每個子實體建立一個表。將建立 Staff 表,但它將包含空值。Staff 表的欄位值必須由 TeachingStaff 和 NonTeachingStaff 表共享。
讓我們考慮與上面相同的示例。
建立實體
在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.entity’** 的包。在給定包下建立一個名為 **Staff.java** 的新 Java 類。Staff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table
@Inheritance( strategy = InheritanceType.TABLE_PER_CLASS )
public class Staff implements Serializable
{
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private int sid;
private String sname;
public Staff( int sid, String sname )
{
super( );
this.sid = sid;
this.sname = sname;
}
public Staff( )
{
super( );
}
public int getSid( )
{
return sid;
}
public void setSid( int sid )
{
this.sid = sid;
}
public String getSname( )
{
return sname;
}
public void setSname( String sname )
{
this.sname = sname;
}
}
為 Staff 類建立一個子類 (class),名為 **TeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。TeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
public class TeachingStaff extends Staff
{
private String qualification;
private String subjectexpertise;
public TeachingStaff( int sid, String sname,
String qualification,String subjectexpertise )
{
super( sid, sname );
this.qualification = qualification;
this.subjectexpertise = subjectexpertise;
}
public TeachingStaff( )
{
super( );
}
public String getQualification( )
{
return qualification;
}
public void setQualification( String qualification )
{
this.qualification = qualification;
}
public String getSubjectexpertise( )
{
return subjectexpertise;
}
public void setSubjectexpertise( String subjectexpertise )
{
this.subjectexpertise = subjectexpertise;
}
}
為 Staff 類建立一個子類 (class),名為 **NonTeachingStaff.java**,放在 **com.tutorialspoint.eclipselink.entity** 包下。NonTeachingStaff 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
public class NonTeachingStaff extends Staff
{
private String areaexpertise;
public NonTeachingStaff( int sid, String sname,
String areaexpertise )
{
super( sid, sname );
this.areaexpertise = areaexpertise;
}
public NonTeachingStaff( )
{
super( );
}
public String getAreaexpertise( )
{
return areaexpertise;
}
public void setAreaexpertise( String areaexpertise )
{
this.areaexpertise = areaexpertise;
}
}
persistence.xml
persistence.xml 檔案包含資料庫的配置資訊和實體類的註冊資訊。xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Staff</class>
<class>com.tutorialspoint.eclipselink.entity.NonTeachingStaff</class>
<class>com.tutorialspoint.eclipselink.entity.TeachingStaff</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
服務類是業務元件的實現部分。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。
在給定包下建立一個名為 **SaveClient.java** 的類,以儲存 Staff、TeachingStaff 和 NonTeachingStaff 類欄位。SaveClient 類如下所示
package com.tutorialspoint.eclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.NonTeachingStaff;
import com.tutorialspoint.eclipselink.entity.TeachingStaff;
public class SaveClient
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Teaching staff entity
TeachingStaff ts1=new TeachingStaff(
1,"Gopal","MSc MEd","Maths");
TeachingStaff ts2=new TeachingStaff(
2, "Manisha", "BSc BEd", "English");
//Non-Teaching Staff entity
NonTeachingStaff nts1=new NonTeachingStaff(
3, "Satish", "Accounts");
NonTeachingStaff nts2=new NonTeachingStaff(
4, "Krishna", "Office Admin");
//storing all entities
entitymanager.persist(ts1);
entitymanager.persist(ts2);
entitymanager.persist(nts1);
entitymanager.persist(nts2);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。有關輸出,請檢查 MySQL 工作臺。
這裡建立了三個表,並且 **Staff** 表包含空記錄。
**TeachingStaff** 的結果如下所示
| Sid | Qualification | Sname | Subjectexpertise |
|---|---|---|---|
| 1 | MSC MED | Gopal | Maths |
| 2 | BSC BED | Manisha | English |
上表 TeachingStaff 包含 Staff 和 TeachingStaff 實體的欄位。
**NonTeachingStaff** 的結果如下所示
| Sid | Areaexpertise | Sname |
|---|---|---|
| 3 | Accounts | Satish |
| 4 | Office Admin | Krishna |
上表 NonTeachingStaff 包含 Staff 和 NonTeachingStaff 實體的欄位。
JPA - 實體關係
本章將帶您瞭解實體之間的關係。通常,關係在資料庫中的表之間更有效。這裡實體類被視為關係表(JPA 的概念),因此實體類之間的關係如下所示
- @ManyToOne 關係
- @OneToMany 關係
- 一對一關係
- 多對多關係
@ManyToOne 關係
實體之間存在多對一關係,其中一個實體(列或列集)被另一個包含唯一值的實體(列或列集)引用。在關係資料庫中,這些關係是透過使用表之間的外部索引鍵/主鍵來實現的。
讓我們考慮一下員工和部門實體之間關係的示例。以單向方式,即從員工到部門,適用多對一關係。這意味著每個員工記錄都包含一個部門 ID,該 ID 應該是部門表中的主鍵。此處,在員工表中,部門 ID 是外部索引鍵。
下圖顯示了這兩個表之間的多對一關係。
在 Eclipse IDE 中建立一個名為 **JPA_Eclipselink_MTO** 的 JPA 專案。下面將討論該專案的所有模組。
建立實體
按照上面給出的圖表建立實體。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoin.eclipselink.entity’** 的包。在給定的包下建立一個名為 **Department.java** 的類。Department 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Department
{
@Id
@GeneratedValue( strategy=GenerationType.AUTO )
private int id;
private String name;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String deptName )
{
this.name = deptName;
}
}
在此關係中建立第二個實體 - Employee 實體類,名為 **Employee.java**,位於 **‘com.tutorialspoint.eclipselink.entity’** 包下。Employee 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Employee
{
@Id
@GeneratedValue( strategy= GenerationType.AUTO )
private int eid;
private String ename;
private double salary;
private String deg;
@ManyToOne
private Department department;
public Employee(int eid,
String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
persistence.xml
需要 persistence.xml 檔案來配置資料庫和實體類的註冊。
建立 JPA 專案時,Eclipse IDE 將建立 Persitence.xml 檔案。配置詳細資訊是使用者指定的。persistence.xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<class>com.tutorialspoint.eclipselink.entity.Department</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
此模組包含服務類,這些類使用屬性初始化來實現關係部分。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。在給定的包下建立名為 **ManyToOne.java** 的 DAO 類。DAO 類如下所示
package com.tutorialspointeclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Department;
import com.tutorialspoint.eclipselink.entity.Employee;
public class ManyToOne
{
public static void main( String[ ] args )
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Create Department Entity
Department department = new Department();
department.setName("Development");
//Store Department
entitymanager.persist(department);
//Create Employee1 Entity
Employee employee1 = new Employee();
employee1.setEname("Satish");
employee1.setSalary(45000.0);
employee1.setDeg("Technical Writer");
employee1.setDepartment(department);
//Create Employee2 Entity
Employee employee2 = new Employee();
employee2.setEname("Krishna");
employee2.setSalary(45000.0);
employee2.setDeg("Technical Writer");
employee2.setDepartment(department);
//Create Employee3 Entity
Employee employee3 = new Employee();
employee3.setEname("Masthanvali");
employee3.setSalary(50000.0);
employee3.setDeg("Technical Writer");
employee3.setDepartment(department);
//Store Employees
entitymanager.persist(employee1);
entitymanager.persist(employee2);
entitymanager.persist(employee3);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。有關輸出,請檢查 MySQL workbench。在此示例中,將建立兩個表。
在 MySQL 介面中傳遞以下查詢,並將顯示 **Department** 表的結果,如下所示
Select * from department
| ID | 名稱 |
|---|---|
| 101 | 開發部 |
在 MySQL 介面中傳遞以下查詢,並將顯示 **Employee** 表的結果,如下所示。
Select * from employee
| Eid | Deg | Ename | Salary | Department_Id |
|---|---|---|---|---|
| 102 | 技術撰稿人 | Satish | 45000 | 101 |
| 103 | 技術撰稿人 | Krishna | 45000 | 101 |
| 104 | 技術撰稿人 | Masthanwali | 50000 | 101 |
在上表中,Deparment_Id 是來自 Department 表的外部索引鍵(引用欄位)。
@OneToMany 關係
在此關係中,一個實體的每一行都引用另一個實體中的許多子記錄。重要的是,子記錄不能有多個父記錄。在一個表 A 和表 B 之間的一對多關係中,表 A 中的每一行都可以連結到表 B 中的一行或多行。
讓我們考慮上面的示例。假設上面示例中的 Employee 和 Department 表以相反的單向方式連線,則關係變為一對多關係。在 Eclipse IDE 中建立一個名為 **JPA_Eclipselink_OTM** 的 JPA 專案。下面將討論該專案的所有模組。
建立實體
按照上面給出的圖表建立實體。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoin.eclipselink.entity’** 的包。在給定的包下建立一個名為 **Department.java** 的類。Department 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Department
{
@Id
@GeneratedValue( strategy=GenerationType.AUTO )
private int id;
private String name;
@OneToMany( targetEntity=Employee.class )
private List employeelist;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String deptName )
{
this.name = deptName;
}
public List getEmployeelist()
{
return employeelist;
}
public void setEmployeelist(List employeelist)
{
this.employeelist = employeelist;
}
}
在此關係中建立第二個實體 - Employee 實體類,名為 **Employee.java**,位於 **‘com.tutorialspoint.eclipselink.entity’** 包下。Employee 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Employee
{
@Id
@GeneratedValue( strategy= GenerationType.AUTO )
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid,
String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
}
persistence.xml
persistence.xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<class>com.tutorialspoint.eclipselink.entity.Department</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
此模組包含服務類,這些類使用屬性初始化來實現關係部分。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。在給定的包下建立名為 **OneToMany.java** 的 DAO 類。DAO 類如下所示
package com.tutorialspointeclipselink.service;
import java.util.List;
import java.util.ArrayList;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Department;
import com.tutorialspoint.eclipselink.entity.Employee;
public class OneToMany
{
public static void main(String[] args)
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Create Employee1 Entity
Employee employee1 = new Employee();
employee1.setEname("Satish");
employee1.setSalary(45000.0);
employee1.setDeg("Technical Writer");
//Create Employee2 Entity
Employee employee2 = new Employee();
employee2.setEname("Krishna");
employee2.setSalary(45000.0);
employee2.setDeg("Technical Writer");
//Create Employee3 Entity
Employee employee3 = new Employee();
employee3.setEname("Masthanvali");
employee3.setSalary(50000.0);
employee3.setDeg("Technical Writer");
//Store Employee
entitymanager.persist(employee1);
entitymanager.persist(employee2);
entitymanager.persist(employee3);
//Create Employeelist
List<Employee> emplist = new ArrayList();
emplist.add(employee1);
emplist.add(employee2);
emplist.add(employee3);
//Create Department Entity
Department department= new Department();
department.setName("Development");
department.setEmployeelist(emplist);
//Store Department
entitymanager.persist(department);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。有關輸出,請檢查 MySQL workbench,如下所示。
在此專案中建立了三個表。在 MySQL 介面中傳遞以下查詢,並將顯示 department_employee 表的結果,如下所示
Select * from department_Id;
| Department_ID | Employee_Eid |
|---|---|
| 254 | 251 |
| 254 | 252 |
| 254 | 253 |
在上表中,**deparment_id** 和 **employee_id** 是來自 department 和 employee 表的外部索引鍵(引用欄位)。
在 MySQL 介面中傳遞以下查詢,並將以表格格式顯示 department 表的結果,如下所示。
Select * from department;
| ID | 名稱 |
|---|---|
| 254 | 開發部 |
在 MySQL 介面中傳遞以下查詢,並將顯示 employee 表的結果,如下所示
Select * from employee;
| Eid | Deg | Ename | Salary |
|---|---|---|---|
| 251 | 技術撰稿人 | Satish | 45000 |
| 252 | 技術撰稿人 | Krishna | 45000 |
| 253 | 技術撰稿人 | Masthanwali | 50000 |
一對一關係
在一對一關係中,一個專案只能連結到另一個專案。這意味著一個實體的每一行都只引用另一個實體的一行。
讓我們考慮上面的示例。**Employee** 和 **Department** 以相反的單向方式,關係是一對一關係。這意味著每個員工只屬於一個部門。在 Eclipse IDE 中建立一個名為 **JPA_Eclipselink_OTO** 的 JPA 專案。下面將討論該專案的所有模組。
建立實體
按照上面給出的圖表建立實體。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoin.eclipselink.entity’** 的包。在給定的包下建立一個名為 **Department.java** 的類。Department 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Department
{
@Id
@GeneratedValue( strategy=GenerationType.AUTO )
private int id;
private String name;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName( )
{
return name;
}
public void setName( String deptName )
{
this.name = deptName;
}
}
在此關係中建立第二個實體 - Employee 實體類,名為 **Employee.java**,位於 **‘com.tutorialspoint.eclipselink.entity’** 包下。Employee 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Employee
{
@Id
@GeneratedValue( strategy= GenerationType.AUTO )
private int eid;
private String ename;
private double salary;
private String deg;
@OneToOne
private Department department;
public Employee(int eid,
String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
public Department getDepartment()
{
return department;
}
public void setDepartment(Department department)
{
this.department = department;
}
}
persistence.xml
persistence.xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<class>com.tutorialspoint.eclipselink.entity.Department</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。在給定的包下建立名為 **OneToOne.java** 的 DAO 類。DAO 類如下所示
package com.tutorialspointeclipselink.service;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Department;
import com.tutorialspoint.eclipselink.entity.Employee;
public class OneToOne
{
public static void main(String[] args)
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Create Department Entity
Department department = new Department();
department.setName("Development");
//Store Department
entitymanager.persist(department);
//Create Employee Entity
Employee employee = new Employee();
employee.setEname("Satish");
employee.setSalary(45000.0);
employee.setDeg("Technical Writer");
employee.setDepartment(department);
//Store Employee
entitymanager.persist(employee);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上收到通知。有關輸出,請檢查 MySQL workbench,如下所示。
在上面的示例中,建立了兩個表。在 MySQL 介面中傳遞以下查詢,並將顯示 department 表的結果,如下所示
Select * from department
| ID | 名稱 |
|---|---|
| 301 | 開發部 |
在 MySQL 介面中傳遞以下查詢,並將顯示 **employee** 表的結果,如下所示
Select * from employee
| Eid | Deg | Ename | Salary | Department_id |
|---|---|---|---|---|
| 302 | 技術撰稿人 | Satish | 45000 | 301 |
多對多關係
多對多關係是指一個實體的一行或多行與另一個實體的多行關聯。
讓我們考慮一下兩個實體之間關係的示例:**班級**和**老師**。以雙向方式,班級和老師都具有多對一關係。這意味著每個班級的記錄都被老師集(教師 ID)引用,這些 ID 應該是教師表中的主鍵,並存儲在 Teacher_Class 表中,反之亦然。這裡,Teachers_Class 表包含兩個外部索引鍵欄位。在 Eclipse IDE 中建立一個名為 **JPA_Eclipselink_MTM** 的 JPA 專案。下面將討論該專案的所有模組。
建立實體
按照上面圖表中顯示的模式建立實體。在 **‘src’** 包下建立一個名為 **‘com.tutorialspoin.eclipselink.entity’** 的包。在給定的包下建立一個名為 **Clas.java** 的類。Department 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Clas
{
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private int cid;
private String cname;
@ManyToMany(targetEntity=Teacher.class)
private Set teacherSet;
public Clas()
{
super();
}
public Clas(int cid,
String cname, Set teacherSet)
{
super();
this.cid = cid;
this.cname = cname;
this.teacherSet = teacherSet;
}
public int getCid()
{
return cid;
}
public void setCid(int cid)
{
this.cid = cid;
}
public String getCname()
{
return cname;
}
public void setCname(String cname)
{
this.cname = cname;
}
public Set getTeacherSet()
{
return teacherSet;
}
public void setTeacherSet(Set teacherSet)
{
this.teacherSet = teacherSet;
}
}
在此關係中建立第二個實體 - Employee 實體類,名為 **Teacher.java**,位於 **‘com.tutorialspoint.eclipselink.entity’** 包下。Employee 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Teacher
{
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private int tid;
private String tname;
private String subject;
@ManyToMany(targetEntity=Clas.class)
private Set clasSet;
public Teacher()
{
super();
}
public Teacher(int tid, String tname, String subject,
Set clasSet)
{
super();
this.tid = tid;
this.tname = tname;
this.subject = subject;
this.clasSet = clasSet;
}
public int getTid()
{
return tid;
}
public void setTid(int tid)
{
this.tid = tid;
}
public String getTname()
{
return tname;
}
public void setTname(String tname)
{
this.tname = tname;
}
public String getSubject()
{
return subject;
}
public void setSubject(String subject)
{
this.subject = subject;
}
public Set getClasSet()
{
return clasSet;
}
public void setClasSet(Set clasSet)
{
this.clasSet = clasSet;
}
}
persistence.xml
persistence.xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<class>com.tutorialspoint.eclipselink.entity.Department</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
在 **‘src’** 包下建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。在給定的包下建立名為 **ManyToMany.java** 的 DAO 類。DAO 類如下所示
package com.tutorialspoint.eclipselink.service;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.tutorialspoint.eclipselink.entity.Clas;
import com.tutorialspoint.eclipselink.entity.Teacher;
public class ManyToMany
{
public static void main(String[] args)
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
entitymanager.getTransaction( ).begin( );
//Create Clas Entity
Clas clas1=new Clas(0,"1st",null);
Clas clas2=new Clas(0,"2nd",null);
Clas clas3=new Clas(0,"3rd",null);
//Store Clas
entitymanager.persist(clas1);
entitymanager.persist(clas2);
entitymanager.persist(clas3);
//Create Clas Set1
Set<Clas> classSet1 = new HashSet();
classSet1.add(clas1);
classSet1.add(clas2);
classSet1.add(clas3);
//Create Clas Set2
Set<Clas> classSet2 = new HashSet();
classSet2.add(clas3);
classSet2.add(clas1);
classSet2.add(clas2);
//Create Clas Set3
Set<Clas> classSet3 = new HashSet();
classSet3.add(clas2);
classSet3.add(clas3);
classSet3.add(clas1);
//Create Teacher Entity
Teacher teacher1 = new Teacher(0,
"Satish","Java",classSet1);
Teacher teacher2 = new Teacher(0,
"Krishna","Adv Java",classSet2);
Teacher teacher3 = new Teacher(0,
"Masthanvali","DB2",classSet3);
//Store Teacher
entitymanager.persist(teacher1);
entitymanager.persist(teacher2);
entitymanager.persist(teacher3);
entitymanager.getTransaction( ).commit( );
entitymanager.close( );
emfactory.close( );
}
}
在此示例專案中,建立了三個表。在 MySQL 介面中傳遞以下查詢,並將顯示 teacher_clas 表的結果,如下所示
Select * form teacher_clas
| Teacher_tid | Classet_cid |
|---|---|
| 354 | 351 |
| 355 | 351 |
| 356 | 351 |
| 354 | 352 |
| 355 | 352 |
| 356 | 352 |
| 354 | 353 |
| 355 | 353 |
| 356 | 353 |
在上表中,**teacher_tid** 是來自 teacher 表的外部索引鍵,**classet_cid** 是來自 class 表的外部索引鍵。因此,不同的老師被分配到不同的班級。
在 MySQL 介面中傳遞以下查詢,並將顯示 teacher 表的結果,如下所示
Select * from teacher
| Tid | 科目 | 姓名 |
|---|---|---|
| 354 | Java | Satish |
| 355 | 高階Java | Krishna |
| 356 | DB2 | Masthanvali |
在 MySQL 介面中傳遞以下查詢,並將顯示 **clas** 表的結果,如下所示
Select * from clas
| Cid | 班級名稱 |
|---|---|
| 351 | 一年級 |
| 352 | 二年級 |
| 353 | 三年級 |
JPA - Criteria API
Criteria 是一個預定義的 API,用於定義實體的查詢。它是定義 JPQL 查詢的替代方法。這些查詢是型別安全的、可移植的,並且易於透過更改語法來修改。與 JPQL 類似,它遵循抽象模式(易於編輯的模式)和嵌入式物件。元資料 API 與 Criteria API 混合在一起,用於為 Criteria 查詢建模持久實體。
Criteria API 的主要優點是可以在編譯時更早地檢測到錯誤。基於字串的 JPQL 查詢和基於 JPA Criteria 的查詢在效能和效率上相同。
Criteria API 的歷史
Criteria 包含在所有版本的 JPA 中,因此 JPA 規範中會通知 Criteria 的每個步驟。
- 在 JPA 2.0 中,開發了 Criteria 查詢 API,對查詢進行了標準化。
- 在 JPA 2.1 中,包含了 Criteria 更新和刪除(批次更新和刪除)。
Criteria 查詢結構
Criteria 和 JPQL 密切相關,並允許在其查詢中使用類似的運算子進行設計。它遵循 **javax.persistence.criteria** 包來設計查詢。查詢結構表示語法 Criteria 查詢。
以下簡單的 Criteria 查詢返回資料來源中實體類的所有例項。
EntityManager em = ...; CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Entity class> cq = cb.createQuery(Entity.class); Root<Entity> from = cq.from(Entity.class); cq.select(Entity); TypedQuery<Entity> q = em.createQuery(cq); List<Entity> allitems = q.getResultList();
該查詢演示了建立 Criteria 的基本步驟。
使用 **EntityManager** 例項建立 CriteriaBuilder 物件。
使用 **CriteriaQuery** 例項建立查詢物件。此查詢物件的屬性將使用查詢的詳細資訊進行修改。
呼叫 **CriteriaQuery.form** 方法來設定查詢根。
呼叫 **CriteriaQuery.select** 來設定結果列表型別。
使用 **TypedQuery<T>** 例項準備要執行的查詢並指定查詢結果的型別。
在 TypedQuery<T> 物件上使用 **getResultList** 方法執行查詢。此查詢返回實體集合,結果儲存在列表中。
Criteria API 示例
讓我們考慮一下員工資料庫的示例。讓我們假設 jpadb.employee 表包含以下記錄
Eid Ename Salary Deg 401 Gopal 40000 Technical Manager 402 Manisha 40000 Proof reader 403 Masthanvali 35000 Technical Writer 404 Satish 30000 Technical writer 405 Krishna 30000 Technical Writer 406 Kiran 35000 Proof reader
在 Eclipse IDE 中建立一個名為 **JPA_Eclipselink_Criteria** 的 JPA 專案。下面將討論該專案的所有模組
建立實體
在 **‘src’** 下建立一個名為 **com.tutorialspoint.eclipselink.entity** 的包
在給定的包下建立一個名為 **Employee.java** 的類。Employee 實體類如下所示
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Employee
{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg)
{
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( )
{
super();
}
public int getEid( )
{
return eid;
}
public void setEid(int eid)
{
this.eid = eid;
}
public String getEname( )
{
return ename;
}
public void setEname(String ename)
{
this.ename = ename;
}
public double getSalary( )
{
return salary;
}
public void setSalary(double salary)
{
this.salary = salary;
}
public String getDeg( )
{
return deg;
}
public void setDeg(String deg)
{
this.deg = deg;
}
@Override
public String toString() {
return "Employee [eid=" + eid + ", ename=" + ename + ", salary="
+ salary + ", deg=" + deg + "]";
}
}
persistence.xml
persistence.xml 檔案如下所示
<?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="Eclipselink_JPA"
transaction-type="RESOURCE_LOCAL">
<class>com.tutorialspoint.eclipselink.entity.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password"
value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
服務類
此模組包含服務類,這些類使用 MetaData API 初始化來實現 Criteria 查詢部分。建立一個名為 **‘com.tutorialspoint.eclipselink.service’** 的包。在給定的包下建立名為 **CriteriaAPI.java** 的類。DAO 類如下所示
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import com.tutorialspoint.eclipselink.entity.Employee;
public class CriteriaApi
{
public static void main(String[] args)
{
EntityManagerFactory emfactory = Persistence.
createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.
createEntityManager( );
CriteriaBuilder criteriaBuilder = entitymanager
.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = criteriaBuilder
.createQuery();
Root<Employee> from = criteriaQuery.from(Employee.class);
//select all records
System.out.println(“Select all records”);
CriteriaQuery<Object> select =criteriaQuery.select(from);
TypedQuery<Object> typedQuery = entitymanager
.createQuery(select);
List<Object> resultlist= typedQuery.getResultList();
for(Object o:resultlist)
{
Employee e=(Employee)o;
System.out.println("EID : "+e.getEid()
+" Ename : "+e.getEname());
}
//Ordering the records
System.out.println(“Select all records by follow ordering”);
CriteriaQuery<Object> select1 = criteriaQuery.select(from);
select1.orderBy(criteriaBuilder.asc(from.get("ename")));
TypedQuery<Object> typedQuery1 = entitymanager
.createQuery(select);
List<Object> resultlist1= typedQuery1.getResultList();
for(Object o:resultlist1)
{
Employee e=(Employee)o;
System.out.println("EID : "+e.getEid()
+" Ename : "+e.getEname());
}
entitymanager.close( );
emfactory.close( );
}
}
編譯並執行上述程式後,您將在 Eclipse IDE 的控制檯面板上獲得以下輸出。
Select All records EID : 401 Ename : Gopal EID : 402 Ename : Manisha EID : 403 Ename : Masthanvali EID : 404 Ename : Satish EID : 405 Ename : Krishna EID : 406 Ename : Kiran Select All records by follow Ordering EID : 401 Ename : Gopal EID : 406 Ename : Kiran EID : 405 Ename : Krishna EID : 402 Ename : Manisha EID : 403 Ename : Masthanvali EID : 404 Ename : Satish