2010-04-22 113 views
0

我在我的項目JPA拋出:IllegalArgumentException異常

public class Blobx { 
@ManyToOne 
private Userx user; 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private Key id; 
} 

public class Index { 
@Id 
private String keyword; 
@OneToMany(cascade = CascadeType.PERSIST) 
private List<Blobx> blobs; 
} 

public class Userx { 
@Id 
private String name; 
@OneToMany(mappedBy = "user") 
private List<Blobx>blobs; 
} 

已經由三個實體類在運行下面的行應用程序引擎拋出一個異常

em.getTransaction().begin(); 
    em.persist(index); 
    em.getTransaction().commit();//exception is thrown 
    em.close(); 

Caused by: java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction. found both Element 


{ 
    type: "Index" 
    name: "function" 
    } 
    and Element { 
    type: "Userx" 
    name: "18580476422013912411" 
    } 

我不能不明白什麼是錯的?

回答

1

發生了什麼(基於錯誤消息)是您正試圖在事務中持久保存包含Blobx es的Index es,其中包含Userx es,它們都位於不同的實體組中。當你打電話給em.persist(index)時,它會級聯堅持其中的所有實體,以及它們內部的所有實體。

將實體組想象爲一組機器。您的一些Index es位於內華達州的A羣。其中包含的Blobx位於緬因州的羣集B中,其中包含的Userx位於德克薩斯州和俄勒岡州的羣集B和羣集C中。它們如何都完全是隨機的,並且(與你的代碼一樣)完全不受你的控制。要求App Engine堅持所有這些不同地理位置的實體,並且知道何時失敗(即在交易中)幾乎是不可能的,並且需要大量的網絡串擾來讓所有各方知道所有其他方都沒有問題。所以這是不允許的。

你想要做的是確保Google將你所有的實體放在一個實體組中,這意味着他們都在一個地理位置。要做到這一點,請閱讀the docs for Transactions,其中描述瞭如何確保您的實體最終在同一個實體組中,這意味着他們將能夠在所有實體上進行事務處理。

現在,實體分組的事情有其不利之處。即數據存儲的速度緩慢和不均勻的利用率(例如,現在所有的實體都在德克薩斯州,俄勒岡州的用戶會看到不必要的緩慢!),所以只有在您需要使用實體組時,才能使用實體組。例如,除非實際必須,否則不要使用級聯持久性,除非實際必須執行此操作。