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; } }
