JPA 實(shí)體管理器

2020-09-03 10:19 更新

實(shí)體管理器概述

實(shí)體管理器(EntityManager)用于管理系統(tǒng)中的實(shí)體,它是實(shí)體與數(shù)據(jù)庫(kù)之間的橋梁,通過調(diào)用實(shí)體管理器的相關(guān)方法可以把實(shí)體持久化到數(shù)據(jù)庫(kù)中,同時(shí)也可以把數(shù)據(jù)庫(kù)中的記錄打包成實(shí)體對(duì)象。

實(shí)體的四種狀態(tài)

在此之前我們要先了解實(shí)體的狀態(tài)及其轉(zhuǎn)換,見下圖

JPA 實(shí)體生命周期有四種狀態(tài)

  • 新建狀態(tài)(New):對(duì)象在保存進(jìn)數(shù)據(jù)庫(kù)之前為臨時(shí)狀態(tài)。此時(shí)數(shù)據(jù)庫(kù)中沒有該對(duì)象的信息,該對(duì)象的ID屬性也為空。如果沒有被持久化,程序退出時(shí)臨時(shí)狀態(tài)的對(duì)象信息將丟失。
  • 托管狀態(tài)(Managed):對(duì)象在保存進(jìn)數(shù)據(jù)庫(kù)后或者從數(shù)據(jù)庫(kù)中加載后、并且沒有脫離Session時(shí)為持久化狀態(tài)。這時(shí)候數(shù)據(jù)庫(kù)中有對(duì)象的信息,改對(duì)象的id為數(shù)據(jù)庫(kù)中對(duì)應(yīng)記錄的主鍵值。由于還在 Session中,持久化狀態(tài)的對(duì)象可以執(zhí)行任何有關(guān)數(shù)據(jù)庫(kù)的操作,例如獲取集合屬性的值等。
  • 游離狀態(tài)(Datached):是對(duì)象曾經(jīng)處于持久化狀態(tài)、但是現(xiàn)在已經(jīng)離開Session了。雖然分離狀態(tài)的對(duì)象有id值,有對(duì)應(yīng)的數(shù)據(jù)庫(kù)記錄,但是已經(jīng)無法執(zhí)行有關(guān)數(shù)據(jù)庫(kù)的操作。例如,讀取延遲加載的集合屬性,可能會(huì)拋出延遲加載異常。
  • 刪除狀態(tài)(Removed):刪除的對(duì)象,有id值,尚且和 Persistence  Context 有關(guān)聯(lián),但是已經(jīng)準(zhǔn)備好從數(shù)據(jù)庫(kù)中刪除。

創(chuàng)建實(shí)體管理器

所有實(shí)體管理器都來自類型?javax.persistence.EntityManagerFactory?的工廠。

以下示例演示為名為“EmployeeService”的持久性單元?jiǎng)?chuàng)建一個(gè)?EntityManagerFactory?:

EntityManagerFactory emf = 
    Persistence.createEntityManagerFactory("EmployeeService");

以下示例演示如何在上一個(gè)示例中獲取的工廠創(chuàng)建實(shí)體管理器:

EntityManager em = emf.createEntityManager();

保存實(shí)體

我們使用實(shí)體管理器來持久化?Employee?的實(shí)例。

Employee emp = new Employee(158);
em.persist(emp);

以下代碼顯示如何在創(chuàng)建新員工并將其保留到數(shù)據(jù)庫(kù)的方法中使用?EntityManager?。

public Employee createEmployee(int id, String name, long salary) {
    Employee emp = new Employee(id);
    emp.setName(name);
    emp.setSalary(salary);
    em.persist(emp);
    return emp;
}

查找實(shí)體

一旦實(shí)體在數(shù)據(jù)庫(kù)中,下一行代碼顯示如何找到它。

Employee emp = em.find(Employee.class, 1);

刪除實(shí)體

要從數(shù)據(jù)庫(kù)中刪除實(shí)體,請(qǐng)從?EntityManager?調(diào)用?remove?方法。

Employee emp = em.find(Employee.class, 1);
em.remove(emp);

更新實(shí)體

要更新實(shí)體,我們可以在被管實(shí)體上調(diào)用?setter?方法。被管實(shí)體是從?EntityManager?返回的實(shí)體。

Employee emp = em.find(Employee.class, 1);
emp.setName("new Name");

事務(wù)

以下代碼顯示如何啟動(dòng)和提交事務(wù)。

em.getTransaction().begin(); Employee emp = new Employee(158); em.persist(emp); em.getTransaction().commit();

查詢

在?JPA?中,有一種稱為?Java?持久性查詢語(yǔ)言(JP QL)的新的查詢語(yǔ)言。

以下示例顯示如何創(chuàng)建動(dòng)態(tài)查詢,然后執(zhí)行它以獲取數(shù)據(jù)庫(kù)中的所有員工。

TypedQuery<Employee> query = 
     em.createQuery("SELECT e FROM Employee e",
                     Employee.class);
List<Employee> emps = query.getResultList();

我們通過在?EntityManager?上發(fā)出?createQuery()?調(diào)用并傳入 JP QL 字符串來創(chuàng)建一個(gè)?TypedQuery<Employee>?對(duì)象。

JP QL 字符串不是指?EMPLOYEE?數(shù)據(jù)庫(kù)表,而是Employee實(shí)體。

例子

以下代碼顯示了一個(gè)簡(jiǎn)單的完全功能類,可用于對(duì)?Employee?實(shí)體發(fā)出典型的創(chuàng)建,讀取,更新和刪除(CRUD)操作。

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

public class EmployeeService {
  protected EntityManager em;

  public EmployeeService(EntityManager em) {
    this.em = em;
  }

  public Employee createEmployee(int id, String name, long salary) {
    Employee emp = new Employee(id);
    emp.setName(name);
    emp.setSalary(salary);
    em.persist(emp);
    return emp;
  }

  public void removeEmployee(int id) {
    Employee emp = findEmployee(id);
    if (emp != null) {
      em.remove(emp);
    }
  }

  public Employee raiseEmployeeSalary(int id, long raise) {
    Employee emp = em.find(Employee.class, id);
    if (emp != null) {
      emp.setSalary(emp.getSalary() + raise);
    }
    return emp;
  }

  public Employee findEmployee(int id) {
    return em.find(Employee.class, id);
  }

  public List<Employee> findAllEmployees() {
    TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e",
        Employee.class);
    return query.getResultList();
  }
}

主類

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence
        .createEntityManagerFactory("EmployeeService");
    EntityManager em = emf.createEntityManager();
    EmployeeService service = new EmployeeService(em);

    em.getTransaction().begin();
    Employee emp = service.createEmployee(1, "Tom", 5000);
    em.getTransaction().commit();
    System.out.println("Persisted " + emp);

    emp = service.findEmployee(1);
    System.out.println("Found " + emp);

    List<Employee> emps = service.findAllEmployees();
    for (Employee e : emps)
      System.out.println("Found employee: " + e);

    em.getTransaction().begin();
    emp = service.raiseEmployeeSalary(1, 1000);
    em.getTransaction().commit();
    System.out.println("Updated " + emp);

    em.getTransaction().begin();
    service.removeEmployee(158);
    em.getTransaction().commit();
    System.out.println("Removed Employee 158");

    em.close();
    emf.close();
  }
}

持久性單元

描述持久性單元的配置在名為 persistence.xml 的XML文件中定義。

每個(gè)持久性單元都被命名。單個(gè) persistence.xml 文件可以包含一個(gè)或多個(gè)命名的持久性單元配置。

以下代碼顯示了 persistence.xml 文件的演示

<persistence>
   <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
      <properties>
         <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
         <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
         <property name="javax.persistence.jdbc.user" value="APP"/>
         <property name="javax.persistence.jdbc.password" value="APP"/>
      </properties>
   </persistence-unit>
</persistence>

persistence.xml 文件應(yīng)放在 META-INF 目錄中。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)