1

I have following entity

@Entity
public class Product implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;
    @Basic
    private String title;
    @Basic
    private double price;
    @Basic
    private String description;
    private Map<String, Integer> map;
}

And then I trying to persist some number of such objects with EntityManager

EntityManager em = EMF.get().createEntityManager();
for (int i = 0; i < 10; i++) {
      Product p = new Product();
      //call setters
      em.persist(p);
}
em.close();

But when call EM's close getting

java.lang.IllegalArgumentException: operating on too many entity groups in a single transaction.

The question is why operating with single entity group ('Product' on my mind) this exception happens?

Thanks.

Ivan
  • 1,446
  • 2
  • 11
  • 25
  • 2
    possible duplicate of [How many objects is "too many" for in a single transaction to Google's DataStore (High Replication)?](http://stackoverflow.com/questions/8251594/how-many-objects-is-too-many-for-in-a-single-transaction-to-googles-datastore) – Jens Jun 08 '14 at 21:44
  • hmm...close to that but that answer doesn't cover my question I think. Docs says "All Datastore operations in a transaction must operate on entities in the same entity group." and in my opinion I'm working with only one group. – Ivan Jun 08 '14 at 21:53
  • 1
    Why do you assume that all objects of type X are in the same Entity Group? They aren't, as that other post says. Either way the restriction is in the datastore itself, not in JPA or the JPA implementation - use that datastore and you have to work around such things – Neil Stockton Jun 09 '14 at 08:28
  • Neil Stockton, probably I made such assumption by mistake. Yep, I understand that JPA/JDO is only contract and real implementation is Datanucleous. Actually I tried to use approach with DatastoreService and raw Entities but got the same. Thanks. – Ivan Jun 09 '14 at 08:34
  • 1
    This doc covers the general idea of entity groups: https://developers.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency. A single kind (in this case Product) is not an Entity Group because updates within an Entity Group are limited to 1 write per second. So if you were implementing a chat server with a "Message" kind, you don't want a limit of 1 message globally per second. Instead, you could have each Message be in an Entity Group for the user who wrote it so that each user is limited to sending 1 message per second. – Patrick Costello Jun 09 '14 at 16:43
  • IMHO the datastore docs miss a clear diagram for people to visualize what an Entity Group "looks" like. I've been procrastinating over creating a blog post about this for (4) years... hope my answer will help. – Michael Técourt Jun 11 '14 at 17:07

1 Answers1

0

All Products are not in the same entity group. Using JPA, Product will be your entity kind. JDO & JPA hide the underlaying datastore structure, which is hierarchical, just like your OS directories for example.

Think of an entity group as a data tree, where your root entity is, well, the tree root. To provide a clear exemple, I'll add a ProductDetail child entity to Product. Let's say each product has many product details :

/** Root entity */
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    // ...

    /** Children entities */
    @OneToMany
    private List<ProductDetail> details;

}

@Entity
public class ProductDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;
}

Your data would translate to the following hierarchical "schema" :

Product(id=1) 
|__ProductDetail(id=2)
|__ProductDetail(id=3)
|__ProductDetail(id=7)

Product(id=4)
|__ProductDetail(id=5)
|__ProductDetail(id=6)
...

As you can see, if your Product entities do not share a common parent entity (e.g. some other class holds a @OneToMany reference to product), each of them is considered a root entity, which means that each product is in its own entity group.

Now what the docs say about transactions on entity groups :

(Using JPA, the difference between a "normal" and XG transaction is handled by the framework)

All Datastore operations in a transaction must operate on entities in the same entity group if the transaction is a single group transaction, or on entities in a maximum of five entity groups if the transaction is a cross-group (XG) transaction.

This is why creating 10 new Product (root) entities in a single datastore transaction will undoubtedly fail.

On the other hand, using the example above, you could create 20 ProductDetail entities in the same transaction if they belong to the same Product entity. (you could update the Product at the same time too)

Michael Técourt
  • 3,457
  • 1
  • 28
  • 45