【问题标题】:jpa IllegalArgumentException exceptionjpa IllegalArgumentException 异常
【发布时间】:2010-04-22 13:01:38
【问题描述】:

我的项目中有三个实体类

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"
  }

我不明白怎么了?

【问题讨论】:

    标签: java google-app-engine jpa


    【解决方案1】:

    发生的事情(基于错误消息)是您试图在事务中持久化 Index,其中包含 Blobxes,其中包含 Userxes,它们都在不同的实体组中.当您调用em.persist(index) 时,它将级联持久化其中的所有实体,以及其中的所有实体。

    将实体组视为一组机器。您的一些Indexes 位于内华达州的集群 A 上。其中包含的 Blobxes 位于缅因州的集群 B 中,其中包含的 Userxes 位于德克萨斯州和俄勒冈州的集群 B 和 C 中。它们如何最终出现完全是随机的,并且(使用您的代码)完全不受您的控制。要求 App Engine 保留所有这些地理上不同的实体并知道一个实体何时失败(即在交易中)几乎是不可能的,并且需要大量的网络串扰才能让所有各方都知道所有其他方都做得很好。所以是不允许的。

    您要做的是确保 Google 将您的所有实体放在一个实体组中,这意味着它们都在一个(地理)位置。为此,请阅读 the docs for Transactions,其中描述了如何确保您的实体最终位于同一实体组中,这意味着他们将能够对所有实体进行事务处理。

    现在,实体分组有其缺点。即数据存储的缓慢和不均匀的利用率(例如,现在您的所有实体都将在德克萨斯州,俄勒冈州的用户将看到不必要的缓慢!),因此如果您绝对需要在所有实体上使用事务,请仅使用实体组。例如,除非您确实需要,否则不要使用级联持久化,或者除非您确实需要,否则不要在事务中使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-07
      • 2011-04-21
      • 2013-03-06
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多