簡體   English   中英

JPA保留了來自ManyToMany關系的已經保留的對象

[英]JPA persists already persisted Objects from a ManyToMany relationship

我在類A和類B之間有一個@ManyToMany關系:類A引用了類B實例的集合,並且此關系配置為CascadeType.ALL。 因此,當A與實體管理器一起保留時,由A引用的B實例也將保留。

A和B都有一個使用GenerationType.IDENTITY策略聲明的ID,以使用MySQL數據庫中的auto_inc。

問題是 :

  1. 我創建一個新的A
  2. 我使用JPQL從entityManager加載了一些現有的B對象
  3. 我將B對象添加到A的B集合中

=> JPA嘗試持久化B對象,盡管它們已經被持久化(它們剛剛已經被加載)。

我不明白為什么它會嘗試再次保留它們,它們已正確加載,並且它們的自動生成的ID也已很好加載。

ManyToMany聲明:

@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name = "ENTRY_ENTITIES", joinColumns =
@JoinColumn(name = "ENTRY", referencedColumnName = "ID"),
inverseJoinColumns = @JoinColumn(name = "ENTITY", referencedColumnName = "ID"))
private List<Entity> entities;

從數據庫加載現有對象的查詢:

T result = (T) entityManager.createQuery("SELECT x FROM " + entityName + " x WHERE x.externalId='" + externalId + "'").getSingleResult();

堅持:

UserTransaction transaction = getTransaction();
try {
    transaction.begin();
    entityManager.persist(entity);
    transaction.commit();
} catch (Throwable t) {
    Logger.getLogger(JpaDao.class.getName()).log(Level.SEVERE, null, t);
}

非常感謝你的幫助!

我不太確定這是造成問題的原因,但是您應該將整個事情都包含在交易中。 不只是持久性部分:

start transaction
load B from DB
create new A
add B to A
commit transaction

正如我在評論中所說,您還有其他設計和編碼問題:

  • 在ManyToXxx關聯上,CascadeType.ALL錯誤。 刪除A時,您不希望刪除A的所有B,因為其他B引用了這些B。 這將導致違反約束(在最佳情況下)或數據庫不一致(在最壞的情況下,如果未定義約束)
  • 不要在查詢中使用字符串連接。 使用參數化查詢。 這將避免引用問題和注入攻擊: SELECT x FROM A x WHERE x.externalId = :externalId

在將這些B實體添加到A時,這些B實體可能是另一個持久性上下文的一部分。您是否在開始事務之后是否嘗試過在B實體上使用合並操作然后再將它們添加到A實體中。

暫無
暫無

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

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