簡體   English   中英

JPA如何管理所有相同應用程序實例中的實體?

[英]How JPA manage entities accross all same application instances?

關於JPA,我有些困惑。

據我所知,JPA具有持久性上下文(也稱為L1緩存),並且它管理所有實體以實現持久性。 並且通過以下過程管理實體。
1.發生查找查詢時,上下文中沒有實體,因此實體管理器向數據庫請求數據
2.將結果另存為持久性contentext中的實體。
3.之后,當查詢發生時,持久性查詢將返回內存實體(如果有)。

但是在第三版中,它在多個實例環境中的工作方式非常令人困惑。 我認為,在多個應用程序實例中,它不能確保所有實例中的實體數據相同。

假設有兩個JPA應用程序實例(所有實例都是相同的負載均衡邏輯)。 該表有2列,一個是id,主鍵,另一個是名稱varchar。

有一行是id = 1,name =“ foobar”

“實例A”通過用戶選擇查詢從數據庫生成ID等於1的實體。
“實例B”還通過用戶選擇查詢從數據庫生成ID等於1的相同實體。
然后通過用戶更新查詢將ID = 1的“實例A”更新實體命名為“ blahblah”。

經過足夠的時間后,沒有對兩個實例進行查詢,如果在“實例B”中發生了更新查詢,即“從名稱= blahblah的表中的表中更新名稱設置新名稱”,我很困惑,它已經有實體,並且其名稱可能沒有更新為“等等”。 那么最后更新查詢在JPA中如何工作?

編輯我意識到我的問題不清楚。 因為提交事務時JPA對DBMS執行DB查詢,所以通常沒有多少應用程序的問題。

為了告訴您為什么要問這個,讓我們假設下面有代碼。

void updateEntities() {
  entityManager.getTransaction().begin();
  List<MyEntity> entities = dao.findAll(); // point1
  for (MyEntity e : entities) {
    e.setValue(e.getValue() + 100); // point2
  }
  entityManager.getTransaction().commit();
}

List<MyEntity> findMyEntities() {
  return dao.findAll(); // point3
}

在其代碼中具有上述代碼塊的兩個實例(兩個都是用於負載平衡的相同代碼實例)。 (並且實體的數量足以容納RAM。)

當客戶端查詢調用findMyEntities方法時A instance在內存中生成實體。
然后客戶端進行下一個查詢,然后請求到達instance Binstance B也生成了內存中的所有實體。 然后到達instance A更新查詢和實例執行的updateEntities以及instance A內存中的所有實體均被更新。
但是這次, instance A的緩存實體和instance B的緩存實體之間有所不同。 但是instance B可能無法知道數據是否已更新。

所以我想知道在上述情況之后何時對instance B進行更新查詢,我相信像下面這樣

  1. 發生用戶查詢。 因此將調用updateEntities方法。
  2. 在point1中,JPA立即對db執行實際查詢,並將查詢結果同步到實體上下文。
  3. point2代碼塊正常執行。

這是正確的嗎?

這是關於事務隔離和鎖定的。 如果要查看其他事務提交的更改,則需要refresh(entity)。 JPA不知道其他事務提交的更改。

Bean的類,通常標記為:

@Stateless沒有狀態,也就是說,即使另一個bean請求相同的信息,它也不會保存狀態。

你可以閱讀:

https://www.tutorialspoint.com/ejb/ejb_stateless_beans.htm

具有狀態的@StateFul將保存狀態,並且在bean結束事務之前它不會改變。

你可以閱讀:

https://www.tutorialspoint.com/ejb/ejb_stateful_beans.htm

並閱讀以下內容:

https://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html

除此之外,您還可以使用方法(通過EntityManager和EntityTransaction):

  • 回滾

  • 紅暈

  • 刷新

  • 承諾

  • setFlushMode()可以具有兩個值:AUTO和COMMIT

看一個例子:

EntityManager em = ....
EntityTransaction et = em.getTransaction();
et.begin();
try{
  em.persist(someObject);
  et.commit();  
}

et.rollback();

最后,您可以指定要在bean中使用的事務類型,可以是:

  • 強制性

  • 需要

  • REQUIRES_NEW

  • SUPPORTS

  • NOT_SUPPORTEED

  • 決不

要使用此屬性:

@TransactionAttribute(TransactionAtributeType.NEVER)
  public float division(float a,float b){
    return (a/b);
  }

這個問題源於我對JPA L1緩存壽命的誤解。

當事務已提交或客戶端請求結束時(在OSIV中),L1緩存無效。

因此,就我而言,L1緩存不與線程或進程共享。
它僅對OSIV中的同一事務或相同請求有效。

因此,實例是否多個都沒有問題。

我感謝有人回答了這個愚蠢的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM