JPA實體狀態分析java
實體狀態詳解docker
實際上就是new了一個普通的JavaBean對象。
1.當1.瞬時對象調用了管理器的persist()後,便可將通常的JavaBean作爲了持久Bean,該Bean的任何屬性改動都會牽涉到數據庫記錄的改動。
2.一旦該記錄flush到數據庫以後,而且事務提交了,那麼此對象不在持久化上下文中,即:變爲了遊離(沒人管的孩子)狀態了。
在遊離狀態的時候調用更新、刷新方法後,遊離狀態對象就變爲了在持久化上下文的託管狀態了。
3.經過管理器的find方法,將實體從數據庫查詢出來後,該實體也就變爲了託管形態。
持久化狀態:數據庫
當處在託管狀態的實體Bean被管理器flush了,那麼就在極短暫的時間進入了持久化狀態,事務提交以後,馬上變爲了遊離狀態。
您能夠把持久化狀態當作實實在在的數據庫記錄。
遊離狀態就是提交到數據庫後,事務commit後實體的狀態,由於事務已經提交了,此時實體的屬性任你如何改變,也不會同步到數據庫,
由於遊離是沒人管的孩子,不在持久化上下文中。
通常要刪除一個持久化對象的時候都是先find出來,以後調用remove方法刪之,此時這個對象就是銷燬對象,實際上就是瞬時對象的另外一種形態罷了。
EntityManager一些經常使用的API(包含query, insert, update, delete操做)緩存
1)get entity —— find() or getReference()服務器
Person person = em.find(Person.class,1);
2)insert —— persist()網絡
Person person = new Person();
person.setName(name);
//把數據保存進數據庫中
em.persist(person);
3)update —— 分2種狀況
狀況1:當實體正在被容器管理時,你能夠調用實體的set方法對數據進行修改,在容器決定flush時(這個由Container自行判斷),更新的數據 纔會同步到數據庫,而不是在調用了set方法對數據進行修改後立刻同步到數據庫。若是你但願修改後的數據立刻同步到數據庫,你能夠調用EntityManager.flush()方法。session
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);
在這種狀況下,調用merge方法,將返回一個新的對象(有id),並對這個新的對象執行insert操做。
在這種狀況下,調用merge方法,將返回一個新的對象,並對該對象執行insert操做。
新對象的id是數據庫中這條記錄的id(好比自增加的id),而不是咱們本身傳入的id。(其實和狀況1的結果是同樣的)
在這種狀況下,調用merge方法,將會從數據庫中查詢對應的記錄,生成新的對象,而後將咱們傳入的對象複製到新的對象,最後執行update操做。
簡單來講,就是更新操做
在這種狀況下,調用merge方法,JPA會把傳入的對象賦值到entityManager的緩存中的對象,而後對entityManager緩存中的對象執行update操做。
(和狀況3的結果同樣)
4)Delete —— Remove().net
Person person = em.find(Person.class, 2);
//若是級聯關係cascade=CascadeType.ALL,在刪除person 時候,也會把級聯對象刪除。
//把cascade屬性設爲cascade=CascadeType.REMOVE 有一樣的效果。
em.remove (person);
Order order = new Order();
order.setId(140);
entityManager.remove(order);
上面這段代碼會拋出異常,由於order是咱們本身建立的對象,也就是遊離對象。必須這樣寫:
Order order = new Order();
order = entityManager.find(Order.class, 140);
entityManager.remove(order);
這段代碼中的order是從數據庫中獲取的,也就是持久化對象
hibernate的delete()方法,只要對象有Id,就能夠刪除
5)HPQL query —— createQuery()
除了使用find()或getReference()方法來得到Entity Bean以外,你還能夠經過JPQL獲得實體Bean。
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()
//咱們可讓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();
… ..
}
}
…
Query query = em.createNativeQuery("update person set age=age+2");
query.executeUpdate();
7)Refresh entity —— refresh()
Order order= entityManager.find(Order.class, 170);
order= entityManager.find(Order.class, 170);
Order order= entityManager.find(Order.class, 170);
entityManager.refresh(order);
Person person = em.find(Person.class, 2);
//若是此時person 對應的記錄在數據庫中已經發生了改變,
//能夠經過refresh()方法獲得最新數據。
em.refresh (person);
8)Check entity是否在EntityManager管理當中 —— contains()
Person person = em.find(Person.class, 2);
。。。
if (em.contains(person)){
//正在被持久化內容管理
}else{
//已經不受持久化內容管理
}
9)分離全部當前正在被管理的實體 —— clear()
10)將實體的改變馬上刷新到數據庫中 —— flush()
例子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();
}
//更新將會在這個方法的末尾被提交和刷新到數據庫中
}
若是你須要在事務提交以前將更新刷新到數據庫中,你能夠直接地調用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()
entityManager.setFlushMode(FlushModeType.COMMIT);
刷新在查詢語句執行前(除了find()和getreference()查詢)或事務提交時才發生,
使用場合:在 大量更新數據的過程當中沒有任何查詢語句(除了find()和getreference()查詢)的執行。
刷新只有在事務提交時才發生,
使用場合:在大量更新數據的過程當中存在查詢語句(除了find()和 getreference()查詢)的執行。
JDBC 性能最大的增進是減小JDBC 驅動與數據庫之間的網絡通信。
FlushModeType.COMMIT模式使更新只在一次的網絡交互中完成,而FlushModeType.AUTO 模式可能須要屢次交互(觸發了多少次Flush 就產生了多少次網絡交互)
12)獲取持久化實現者的引用 —— getDelegate()
HibernateEntityManager manager = (HibernateEntityManager)em.getDelegate();
13)判斷當前的實體管理器是不是打開狀態--isOpen ()
14)返回資源層的事務對象。EntityTransaction實例能夠用於開始和提交多個事務--getTransaction ()
15)大量數據分批提交
有的時候咱們須要循環保存數據,當保存大量數據的時候,
若是到最後才提交全部數據,那麼數據庫的負載可能會比較大。咱們能夠這樣作,每30個記錄就提交(flush)一次。
代碼以下(每到30條記錄的時候就強制提交):
public void updateBatch(List<Z> list) {
for (int i = 0; i < list.size(); i++) {
entityManager.merge(list.get(i)); //變成託管狀態
if (i % 30 == 0) {
entityManager.flush(); //變成持久化狀態
entityManager.clear(); //變成遊離狀態
}
}
}
public void saveBatch(List<Z> list) {
for (int i = 0; i < list.size(); i++) {
entityManager.persist(list.get(i)); //變成託管狀態
if (i % 30 == 0) {
entityManager.flush(); //變成持久化狀態
entityManager.clear(); //變成遊離狀態
}
}
}
參考來源: http://blog.csdn.net/fobdddf/article/details/19479073
參考來源: http://blog.csdn.net/dufufd/article/details/54408727
參考來源:http://toknowme.iteye.com/blog/2235981