JPA EntityManager詳解


EntityManager是JPA中用於增刪改查的接口,它的作用相當於一座橋梁,連接內存中的java對象和數據庫的數據存儲。其主要的方法定義如下:


既然EntityManager只是一個接口,那么誰來負責實現它呢?就是實現了JPA的廠商,例如EclipseLink,Hibernate等等。那么如何獲得EntityManager對象呢?這取決於你的EntityManger對象的托管方式,主要有以下兩種方式:

  • 容器托管的EntityManager對象
  • 應用托管的EntityManager對象

容器托管的EntityManager對象

容器托管的EntityManager對象最為簡單,編程人員不需要考慮EntityManger的連接,釋放以及復雜的事務問題等等,所有這些都交給容器來完成。

EntityManger && PersistenceContext

被EntityManager持久化到數據庫中的對象,或者從數據庫拉入內存中的對象,也會同時被一個持久化上下文(PersistenceContext)管理。這些被管理的對象統稱為受管對象(Managed Object),每個受管對象都有一個唯一的id。EntityManager和PersistenceContext之間的關系,一般可以是多對一的,即多個EntityManager可以同時指向一個PersistenceContext。這其實很好理解,就是EntityManager雖然有多個實例,但是它們背后的持久化上下文卻只有一個,這樣就保證了多個EntityManager所管理的受管對象擁有的ID是唯一的。

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

@PersistenceContext private EntityManager em;

應用托管的EntityManager對象

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

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

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

EntityManagerFactory && PersistenceUnit

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

 

 

那么EntityManagerFactory又是通過何種方法得到的呢?這得分兩種環境來討論:

  • Java EE
  • Java SE

Java EE環境獲得EntityManagerFavctory

在JavaEE環境下,一般通過PersistenceUnit注入的方式引入:

@PersistenceUnit(unitName="jpa-1") private EntityManagerFactory emf;

Java SE環境獲得EntityManagerFavctory

在JavaSE環境下,可以通過Persistence類得到具體的EntityManagerFactory實現:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-1");

 

entityManage使用:

package com.idea.repository.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.collections.MapUtils;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class BaseRepositoryImpl {

    protected final Logger LOG = LoggerFactory.getLogger(getClass());

    @PersistenceContext
    private EntityManager entityManager;

    protected List getResultList(String sql, Map<String, Object> param) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        // 設置參數
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                nativeQuery.setParameter(entry.getKey(), entry.getValue());
            }
        }
        nativeQuery.unwrap(org.hibernate.SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List mapList = nativeQuery.getResultList();
        return mapList;
    }

    protected Object getSingleResult(String sql, Map<String, Object> param) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                nativeQuery.setParameter(entry.getKey(), entry.getValue());
            }
        }
        nativeQuery.unwrap(org.hibernate.SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return nativeQuery.getSingleResult();
    }

    protected Page getPageResultList(String sql, Map<String, Object> param, Pageable pageRequest) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        // 設置參數
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                nativeQuery.setParameter(entry.getKey(), entry.getValue());
            }
        }
        Assert.notNull(nativeQuery,"SQL執行");

        Long total = count(sql, param);

        if (total == null) {
            return null;
        }
        // 設置分頁參數
        nativeQuery.setFirstResult(pageRequest.getOffset());
        nativeQuery.setMaxResults(pageRequest.getPageSize());

        nativeQuery.unwrap(org.hibernate.SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List mapList = nativeQuery.getResultList();

        List<Map<String, Object>> content = total > pageRequest.getOffset() ? mapList : Collections.emptyList();

        return new PageImpl<>(content, pageRequest, total);
    }

    /**
     * 批量刪除操作
     */
    public int excuteBatchDelete(String sql, Map<String, Object> param) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        /*
         * if (map != null && map.size() > 0) { for (Map.Entry<String, List<Object>>
         * entry : map.entrySet()) { nativeQuery.setParameter(entry.getKey(),
         * entry.getValue()); } }
         */
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                nativeQuery.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return nativeQuery.executeUpdate();
    }

    protected Long count(String sql, Map<String, Object> param) {
        String countSql = "select count(*) from (" + sql + ") a";
        Query countQuery = entityManager.createNativeQuery(countSql);

        // 設置參數
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                countQuery.setParameter(entry.getKey(), entry.getValue());
            }
        }
        Assert.notNull(countQuery,"SQL執行");
        Long total = 0L;
        Object totalObj = countQuery.getSingleResult();
        try {
            if (totalObj != null) {
                if (totalObj instanceof BigDecimal) {
                    BigDecimal bd = (BigDecimal) totalObj;
                    total = bd.longValue();
                } else if (totalObj instanceof BigInteger) {
                    BigInteger bd = (BigInteger) totalObj;
                    total = bd.longValue();
                } else {
                    total = Long.parseLong(totalObj.toString());
                }
            }
        } catch (Exception e) {
            LOG.error("不支持該數據庫count返回類型!!");
        }
        return total;
    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM