2010-04-22 117 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,其中描述了如何确保您的实体最终在同一个实体组中,这意味着他们将能够在所有实体上进行事务处理。

现在,实体分组的事情有其不利之处。即数据存储的速度缓慢和不均匀的利用率(例如,现在所有的实体都在德克萨斯州,俄勒冈州的用户会看到不必要的缓慢!),所以只有在您需要使用实体组时,才能使用实体组。例如,除非实际必须,否则不要使用级联持久性,除非实际必须执行此操作。