A list of StructuredProperties in NDB is modelled by a number of repeated properties, one repeated property per property of the StructuredProperty's model class. (See here: https://developers.google.com/appengine/docs/python/ndb/properties#structured.)
The closed equivalent I have found with JPA on Google App Engine is an @Embedded list of @Embeddables. The storage format, however, is now different. The GAE/J plugin for JPA generates one column per embedded entity per property of the embedded entity (see here: http://datanucleus-appengine.googlecode.com/svn-history/r979/trunk/src/com/google/appengine/datanucleus/StoreFieldManager.java). (For long lists, this generates rows with many, many columns, for example.)
Is there an easy built-in way to copy NDB's way to cope with repeated composite values using JPA or JDO?
ADDED:
For those more comfortable with Java than Python, I have found that the Java-based Objectify framework stores collections of embedded classes in the same way as NDB on Python: http://code.google.com/p/objectify-appengine/wiki/Entities#Embedding, which is the way I want to achieve with JPA (or JDO):
For convenience, I am copying their example here:
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
@Embed
class LevelTwo {
String bar;
}
@Embed
class LevelOne {
String foo;
LevelTwo two
}
@Entity
class EntityWithEmbeddedCollection {
@Id Long id;
List<LevelOne> ones = new ArrayList<LevelOne>();
}
Using this setup, run the following code:
EntityWithEmbeddedCollection ent = new EntityWithEmbeddedCollection();
for (int i=1; i<=4; i++) {
LevelOne one = new LevelOne();
one.foo = "foo" + i;
one.two = new LevelTwo();
one.two.bar = "bar" + i;
ent.ones.add(one);
}
ofy().save().entity(ent);
The resulting row layout (using repeated properties on the Datastore level) is then:
ones.foo: ["foo1", "foo2", "foo3", "foo4"]
ones.two.bar: ["bar1", "bar2", "bar3", "bar4"]