簡體   English   中英

如何在多線程環境中處理JPA OneToMany關系

[英]How to handle JPA OneToMany relations in a multi-threaded environment

我有兩個相互鏈接的JPA實體。 一個人可以是零個或一個組的成員。 一個組可以有零個或多個成員。

@Entity
public class PersonEntity {

    @ManyToOne
    @JoinColumn(name = "GROUP_ID")
    private GroupEntity group;
}

@Entity
public class GroupEntity {

    @OneToMany(mappedBy = "group", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
    private Collection<PersonEntity> persons;

}

我遇到的問題是多個線程可以將人員刪除/添加到組中。 因此,當兩個線程從同一組中刪除一個人時,每個線程都不知道另一線程中發生了什么。

  1. personA和personB屬於組1
  2. 線程1從組1中刪除人員A
  3. 線程2從group1中刪除personB
  4. Thread1對personB進行一些后處理
  5. Thread2對personA進行一些后處理

我知道我可以將所有這些都包裝在一個同步塊中,但是如果應用程序在共享數據庫的多台計算機上運行,​​那將無濟於事。

JPA如何知道GroupEntity上的集合已被另一個線程更改?

您對同步塊是正確的:這不適用於JVM

使用數據庫鎖定策略來處理對實體的並發更新

相反,您要考慮數據庫鎖定策略並使用數據庫事務。 JPA支持樂觀鎖定和悲觀鎖定 通常,您可以通過使用版本字段來跟蹤對每個實體的更新的樂觀鎖定來獲得更好的性能。

在您的方案中,如果每個線程都使用樂觀鎖定在一個數據庫中執行其刪除和更新操作,則一個線程將成功,而另一個線程將拋出鎖定異常,因為它試圖更新已刪除的實體

使用聯接表來消除對組成員資格和Person屬性的修改之間的爭用

假設從該組中刪除該人員不會刪除該人員,則在這種情況下可能存在另一種方法來刪除競爭。 通常,在一對多關系中,“人員”行將保留對其所屬組ID的引用。 這將導致線程1和線程2競爭對“個人”行的更新。 相反,您可以將一對多關系移動到單獨的聯接表,以便線程1可以在線程2對PersonA進行后期處理的同時將PersonA從Group1中刪除。

關於在JVM之間同步關系集合

JPA在企業應用程序體系結構模式中實現了幾種持久性模式Martin Fowler細節。 這些模式之一是工作單元,它跟蹤“會話”期間所做的更改。 我認為Thread1和Thread2在不同的工作單元中工作,因此它們應避免嘗試同步其從數據庫中檢索的數據的內存中緩存。 取而代之的是,Thread1在下一次查詢數據庫時將獲取Thread2的更改。 讓數據庫擁有跨分布式系統同步狀態的關注。

如果您需要管理分布式事務,請查看JTA 但是,我不確定哪個JPA提供程序能夠在分布式事務中分配其工作單元的內存狀態。 我會嘗試避免這種情況,而不是處理

暫無
暫無

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

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