EntityManager一些常用的API

1)get entity —— find() or getReference() 

  Person person = em.find(Person.class,1); 

  當在數據庫中沒有找到記錄時,getReference()和find()是有區別的,find()方法會返回null,而getReference() 方法會拋出javax.persistence.EntityNotFoundException例外,另外getReference()方法不保證 entity Bean已被初始化。如果傳遞進getReference()或find()方法的參數不是實體Bean,都會引發 IllegalArgumentException例外 

  2)insert —— persist() 

  Person person = new Person(); 

  person.setName(name); 

  //把數據保存進數據庫中 

  em.persist(person); 

  如果傳遞進persist()方法的參數不是實體Bean,會引發IllegalArgumentException 

  3)update —— 分2種情況 

  情況1:當實體正在被容器管理時,你可以調用實體的set方法對數據進行修改,在容器決定flush時(這個由container自行判斷),更新的數據 纔會同步到數據庫,而不是在調用了set方法對數據進行修改後馬上同步到數據庫。如果你希望修改後的數據馬上同步到數據庫,你可以調用 EntityManager.flush()方法。 

  public void updatePerson() { 

  try { 

  Person person = em.find(Person.class, 1); 

  person.setName("lihuoming"); //方法執行完後即可更新數據 

  } catch (Exception e) { 

  e.printStackTrace(); 

  } 

  } 

  情況2:在實體Bean已經脫離了EntityManager的管理時,你調用實體的set方法對數據進行修改是無法同步更改到數據庫的。你必須調用 EntityManager.merge()方法。調用之後,在容器決定flush時(這個由container自行判斷),更新的數據纔會同步到數據 庫。如果你希望修改後的數據馬上同步到數據庫,你可以調用EntityManager.flush()方法。 

  public boolean updatePerson(Person person) { 

  try { 

  em.merge(person); 

  } catch (Exception e) { 

  e.printStackTrace(); 

  return false; 

  } 

  return true; 

  } 

  下面的代碼會調用上面的方法。因爲下面的第二行代碼把實體Bean 返回到了客戶端,這時的實體Bean已經脫離了容器的管理,在客戶端對實體Bean進行修改,最後把他返回給EJB 容器進行更新操作: 

  PersonDAO persondao = (PersonDAO) ctx.lookup("PersonDAOBean/remote"); 

  Person person = persondao.getPersonByID(1); //此時的person 已經脫離容器的管理 

  person.setName("張小豔"); 

  persondao.updatePerson(person); 

  執行em.merge(person)方法時,容器的工作規則: 

  1> 如果此時容器中已經存在一個受容器管理的具有相同ID的person實例,容器將會把參數person的內容拷貝進這個受管理的實例,merge()方法 返回受管理的實例,但參數person仍然是分離的不受管理的。容器在決定Flush時把實例同步到數據庫中。 

  2>容器中不存在具有相同ID的person實例。容器根據傳進的person參數Copy出一個受容器管理的person實例,同時 merge()方法會返回出這個受管理的實例,但參數person仍然是分離的不受管理的。容器在決定Flush時把實例同步到數據庫中。 

  如果傳遞進merge ()方法的參數不是實體Bean,會引發一個IllegalArgumentException。 

  4)Delete —— Remove() 

  Person person = em.find(Person.class, 2); 

  //如果級聯關係cascade=CascadeType.ALL,在刪除person 時候,也會把級聯對象刪除。 

  //把cascade屬性設爲cascade=CascadeType.REMOVE 有同樣的效果。 

  em.remove (person); 

  如果傳遞進remove ()方法的參數不是實體Bean,會引發一個IllegalArgumentException 

  5)HPQL query —— createQuery() 

  除了使用find()或getReference()方法來獲得Entity Bean之外,你還可以通過JPQL得到實體Bean。 

  要執行JPQL語句,你必須通過EntityManager的createQuery()或createNamedQuery()方法創建一個Query 對象 

  Query query = em.createQuery("select p from Person p where p. name=’黎明’"); 

  List result = query.getResultList(); 

  Iterator iterator = result.iterator(); 

while( iterator.hasNext() ){ 

  //處理Person 

  } 



  // 執行更新語句 

  Query query = em.createQuery("update Person as p set p.name =?1 where p. personid=?2"); 

  query.setParameter(1, “黎明”); 

  query.setParameter(2, new Integer(1) ); 

  int result = query.executeUpdate(); //影響的記錄數 



  // 執行更新語句 

  Query query = em.createQuery("delete from Person"); 

  int result = query.executeUpdate(); //影響的記錄數 

  6)SQL query —— createNaiveQuery() 

  注意:該方法是針對SQL語句,而不是HPQL語句 

  //我們可以讓EJB3 Persistence 運行環境將列值直接填充入一個Entity 的實例, 

  //並將實例作爲結果返回. 

  Query query = em.createNativeQuery("select * from person", Person.class); 

  List result = query.getResultList(); 

  if (result!=null){ 

  Iterator iterator = result.iterator(); 

  while( iterator.hasNext() ){ 

  Person person= (Person)iterator.next(); 

.. 

  } 

  } 



  // 直接通過SQL 執行更新語句 

  Query query = em.createNativeQuery("update person set age=age+2"); 

  query.executeUpdate(); 

  7)Refresh entity —— refresh() 

  如果你懷疑當前被管理的實體已經不是數據庫中最新的數據,你可以通過refresh()方法刷新實體,容器會把數據庫中的新值重寫進實體。這種情況一般發 生在你獲取了實體之後,有人更新了數據庫中的記錄,這時你需要得到最新的數據。當然你再次調用find()或getReference()方法也可以得到 最新數據,但這種做法並不優雅。 

  Person person = em.find(Person.class, 2); 

  //如果此時person 對應的記錄在數據庫中已經發生了改變, 

  //可以通過refresh()方法得到最新數據。 

  em.refresh (person); 

  8)Check entity是否在EntityManager管理當中 —— contains() 

  contains()方法使用一個實體作爲參數,如果這個實體對象當前正被持久化內容管理,返回值爲true,否則爲false。如果傳遞的參數不是實體 Bean,將會引發一個IllegalArgumentException. 

  Person person = em.find(Person.class, 2); 

  。。。 

  if (em.contains(person)){ 

  //正在被持久化內容管理 

  }else{ 

  //已經不受持久化內容管理 

  } 

  9)分離所有當前正在被管理的實體 —— clear() 

  在處理大量實體的時候,如果你不把已經處理過的實體從EntityManager中分離出來,將會消耗你大量的內存。調用EntityManager 的clear()方法後,所有正在被管理的實體將會從持久化內容中分離出來。有一點需要說明下,在事務沒有提交前(事務默認在調用堆棧的最後提交,如:方 法的返回),如果調用clear()方法,之前對實體所作的任何改變將會掉失,所以建議你在調用clear()方法之前先調用flush()方法保存更 改。 

  10) 將實體的改變立刻刷新到數據庫中 —— flush() 

  當EntityManager對象在一個session bean 中使用時,它是和服務器的事務上下文綁定的。EntityManager在服務器的事務提交時提交併且同步它的內容。在一個session bean 中,服務器的事務默認地會在調用堆棧的最後提交(如:方法的返回)。 

  例子1:在方法返回時才提交事務 

  public void updatePerson(Person person) { 

  try { 

  Person person = em.find(Person.class, 2); 

  person.setName("lihuoming"); 

  em.merge(person); 

  //後面還有衆多修改操作 

  } catch (Exception e) { 

  e.printStackTrace(); 

  } 

  //更新將會在這個方法的末尾被提交和刷新到數據庫中 

  } 

  爲了只在當事務提交時纔將改變更新到數據庫中,容器將所有數據庫操作集中到一個批處理中,這樣就減少了代價昂貴的與數據庫的交互。當你調用 persist( ), merge( )或remove( )這些方法時,更新並不會立刻同步到數據庫中,直到容器決定刷新到數據庫中時纔會執行,默認情況下,容器決定刷新是在“相關查詢”執行前或事務提交時發 生,當然“相關查詢”除find()和getreference()之外,這兩個方法是不會引起容器觸發刷新動作的,默認的刷新模式是可以改變的,具體請 

  考參下節。 

  如果你需要在事務提交之前將更新刷新到數據庫中,你可以直接地調用EntityManager.flush()方法。這種情況下,你可以手工地來刷新數據 庫以獲得對數據庫操作的最大控制。 

  public void updatePerson(Person person) { 

  try { 

  Person person = em.find(Person.class, 2); 

  person.setName("lihuoming"); 

  em.merge(person); 

  em.flush();//手動將更新立刻刷新進數據庫 

  //後面還有衆多修改操作 

  } catch (Exception e) { 

  e.printStackTrace(); 

  } 

  } 

  11) 改變實體管理器的Flush模式 —— setFlushMode() 

  的Flush模式有2種類型:AUTO and COMMIT。AUTO爲缺省模式。你可以改變他的值,如下: 

  entityManager.setFlushMode(FlushModeType.COMMIT); 

  FlushModeType.AUTO:刷新在查詢語句執行前(除了find()和getreference()查詢)或事務提交時才發生,使用場合:在 大量更新數據的過程中沒有任何查詢語句(除了find()和getreference()查詢)的執行。

FlushModeType.COMMIT:刷新只有在事務提交時才發生,使用場合:在大量更新數據的過程中存在查詢語句(除了find()和 getreference()查詢)的執行。 

  其實上面兩種模式最終反映的結果是:JDBC 驅動跟數據庫交互的次數。JDBC 性能最大的增進是減少JDBC 驅動與數據庫之間的網絡通訊。FlushModeType.COMMIT模式使更新只在一次的網絡交互中完成,而FlushModeType.AUTO 模式可能需要多次交互(觸發了多少次Flush 就產生了多少次網絡交互) 

  12) 獲取持久化實現者的引用 —— getDelegate() 

  用過getDelegate()方法,你可以獲取EntityManager持久化實現者的引用,如Jboss EJB3的持久化產品採用Hibernate,可以通過getDelegate()方法獲取對他的訪問,如: 

  HibernateEntityManager manager = (HibernateEntityManager)em.getDelegate(); 

  獲得對Hibernate的引用後,可以直接面對Hibernate進行編碼,不過這種方法並不可取,強烈建議不要使用。在Weblogic 中,你也可以通過此方法獲取對Kodo 的訪問。

 

發佈了29 篇原創文章 · 獲贊 16 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章