天天看點

JPA EntityManager接口詳解

分享知識 傳遞快樂

在上章的後面我們已經講了JPA與Hibernater的之間的聯系,接下我們談談JPA的常用操作。

常用Hibernate的小夥伴都熟悉要想擷取資料庫資料,通常會用到SessionFactory和Session兩個接口下的方法來擷取資料。而在SpringBoot+Hibernate整合用的則是JPA操作規範。

使用JPA規範是不能用@Autowired直接注入SessionFactory的,否則運作時會出現異常。JPA提供了EntityManager、EntityManagerFactory兩個接口來代替SessionFactory完成的操作。

EntityManager、EntityManagerFactory是JPA中用于增删改查的接口,它的作用相當于一座橋梁,連接配接記憶體中的java對象和資料庫的資料存儲。

EntityManager接口

EntityManger對象的托管方式,主要有以下兩種方式:

容器托管的EntityManager對象

容器托管的EntityManager對象最為簡單,程式設計人員不需要考慮EntityManger的連接配接,釋放以及複雜的事務問題等等,所有這些都交給容器來完成。被EntityManager持久化到資料庫中的對象,或者從資料庫拉入記憶體中的對象,也會同時被一個持久化上下文(PersistenceContext)管理。這些被管理的對象統稱為受管對象(Managed Object),每個受管對象都有一個唯一的id。EntityManager和PersistenceContext之間的關系,一般可以是多對一的,即多個EntityManager可以同時指向一個PersistenceContext。這其實很好了解,就是EntityManager雖然有多個執行個體,但是它們背後的持久化上下文卻隻有一個,這樣就保證了多個EntityManager所管理的受管對象擁有的ID是唯一的。

受到容器托管的EntityManager可以直接通過注解@PersistenceContext注入的方式來獲得:

@PersistenceContext
private EntityManager entityManager ;      
應用托管的EntityManager對象

應用托管的EntityManager對象,程式員需要手動地控制它的釋放和連接配接、手動地控制事務等。但這種獲得應用托管的 EntityManager對象的方式,不僅可以在EJB容器中應用,也可以使 JPA脫離EJB容器,而與任何的Java環境內建,比如說Web容器、J2SE環境等。是以從某種角度上來說,這種方式是JPA能夠獨立于EJB環境運 行的基礎。

理想狀态下,最好是選用容器托管的EntityManager對象的方式,但在特殊的環境下,還是需要使用應用托管的EntityManager對象這種方式。

應用托管的EntityManger對象,通過EntityManagerFactory來獲得。

EntityManagerFactory接口中使用的最為頻繁的就是第一個createEntityManager(),它能夠建立并傳回得到一個EntityManager接口的實作。既然是一個用于建立EntityManager接口的工廠接口,想必就會有一個用于控制如何生産的配置場所。這個配置場所就是上圖中提到的持久化單元(Persistence Unit)。典型的比如在META-INF檔案夾中建立的persistence.xml檔案,其中就可以定義一個或者多個持久化單元。

受到應用托管的EntityManager可以直接通過注解@PersistenceUnit注入的方式來獲得:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;      

也可以通過配置的XML來擷取,一個典型的persistence.xml檔案如下:

JPA EntityManager接口詳解
@PersistenceUnit(unitName="jpa-1")
private EntityManagerFactory entityManagerFactory ;      

示例

package com.xh.ssh.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;

import org.springframework.stereotype.Repository;

import com.xh.ssh.model.WebTask;


@Repository
public class WebTaskDao {

  // 方法一
  // @Autowired
  // private EntityManagerFactory entityManagerFactory;
  //
  // public Session getSession() {
  // // 這種方式需要手動關閉session
  // // return entityManagerFactory.unwrap(SessionFactory.class).openSession();
  //
  // // 這種方式會自動關閉session,但是要配置current_session_context_class,并且需要使用事務
  // //spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
  // return entityManagerFactory.unwrap(SessionFactory.class).getCurrentSession();
  // }

  // 方法二
  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;

  // 方法三
  @PersistenceContext
  private EntityManager entityManager;

  public List<WebTask> loadAll() {
    String hql = "FROM WebTask";
    // return getSession().createQuery(hql).list();

    // EntityManager entityManager = entityManagerFactory.createEntityManager();
    return entityManager.createQuery(hql).getResultList();
  }

}      

繼續閱讀