How do we create a parent key which is an encoded string? Example:
class Parent {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String mEncKey;
}
class Child {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String mEncKey;
// In the doc examples, they have Key as the type here.
#Persistent
#Extension(vendorName="datanucleus", key="gae.parent-pk", value="true")
private String mParentEncKey;
}
yeah I'm not sure how to make mParentEncKey an encoded string type, because the 'key' label is already being used? I would need something like?:
key="gae.parent-pk.encoded-pk"
not sure - is that possible?
Thanks
I have found a solution for this, you can now map owned relations in a portable manner, check out blog.
This discussion says to just use gae.parent-pk - GAE will automatically use an encoded string value for a parent key field in Child.
https://groups.google.com/group/google-appengine-java/browse_thread/thread/43e38d0bc8a41bbd/0f0f86693330c1b2
Related
So I am not having any luck with loading the venue and artist object when I load my even object. Basically when I create an event, I load the specific artist and specific venue and save the key in the event's artistKey and venueKey fields. However, when I load even it is always null. I have tried annotations "#Persistent(defaultFetchGroup = "true")" and also "#Persistent(mappedBy = "venue") #Element(dependent = "true")" on my venue and artist with no luck as artist/venue still come up as null when I load an event (the keys are there). When I try the defaultFetchGroup it says I cannot load a parent if it has already been persisted, which make sense I guess.
public class Event {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent
private Key artistKey;
#Persistent
private Key venueKey;
private Artist artist;
private Venue venue;
//other fields
//getters and setters
}
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Venue {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
//other fields
//getters and setters
}
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Artist {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
//other fields
//getters and setters
}
with relations (in GAE) you have to pay attention to whether they are owned (stored with the owning object in the datastore) or unowned (like they are in all other datastores). You can mark relations as #Unowned if the latter. GAE has some restrictions around entity groups that impact on this - see their docs
I have the following two entities:
#Entity
public class SupermarketChain {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String key;
#OneToMany(mappedBy = "supermarketChain")
#Basic
private List<Supermarket> supermarkets;
}
#Entity
public class Supermarket {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String key;
#ManyToOne(optional=true)
private SupermarketChain supermarketChain;
}
When I'm deleting a parent with em.remove(SupermarketChain.class, key), all orphans will be deleted too. I read the relevant paragraph in the documentation, even tried it with JDO with #Element(dependent = "false") but the problem remains. How can I retain the orphans in that relation?
Retaining an orphan makes no sense. In v1 of GAE JDO/JPA all relations are "owned" so you have to have a parent of any child. And if the parent no longer exists then the child is deleted. Always.
In v2 of GAE JDO/JPA you will also be able to have unowned objects, hence there is no "parent" and so they can continue to exist after.
Hey guys, my question is about persisting an entity in JDO. I have created a class, StoredOPDSFeed, whose members persist correctly. However, none of its member objects persist correctly. The class is as follows:
#PersistenceCapable
public class StorableOPDSFeed implements Serializable {
private static final long serialVersionUID = 1L;
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String primaryKey;
#Persistent
private String locale;
#Persistent
private Date parseDate;
#Persistent
private String title;
#Persistent
private String href;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSEntry> entries;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSLink> links = new ArrayList<OPDSLink>();
#Persistent
#Embedded
private SearchDescription searchDescription;
#Persistent
private boolean isStart = false;
#Persistent
#Element(dependent = "true")
private ArrayList<OPDSFacetGroup> facet_groups = new ArrayList<OPDSFacetGroup>();
... and accessors, etc.
}
All of the simple members such as locale, title, href, etc persist correctly. However, all of the complex ones such as searchDescription do not appear in the datastore. There is no reference to them whatsoever, no foreign key, nothing. It's like they are completely ignored. Does anyone have any idea why?
Per request, here is the code for OPDSLink:
#PersistenceCapable
public class OPDSLink implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String encodedKey;
private static final long serialVersionUID = 1L;
#Persistent
private String href;
#Persistent
private String rel;
#Persistent
private String type;
#Persistent
private String price;
#Persistent
private String currency;
#Persistent
private String dcformat;
#Persistent
private String title;
... and accessors, etc.
}
The GAE JDO documentation states that in one-to-one relationships both involved entities require a key field.
http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html#Owned_One_to_One_Relationships
If the other entity is embedded as intended in your example, the other class (e.g. SearchDescription) requires a #EmbeddedOnly annotation:
http://code.google.com/appengine/docs/java/datastore/jdo/dataclasses.html#Embedded_Classes
In general I found the the following blog interview a good starting point to see what the GAE JDO implementation supports and what not (especially in comparison to third party frameworks such as Objectify and Twig):
http://borglin.net/gwt-project/?page_id=604
I have been trying to learn and creating a sample project using GWT/GAE/GoogleDatastore.
Am just trying to figure out what would be the best way to design the data model for a learning management system. Let's say in the traditional way the following are the entities.....
User
Role
UserCourses
Courses
Subjects
Materials
User is one to one to Role
Courses is one to many with Subjects
Subjects is one to many with Materials
Users is Many to Many with Courses using UserCourses
Can someone guide me what would be the best possible way to represent this in JDO ?
---> Extension of the question.
Thank You Shifty, but am completely stuck with unowned relationship model... trying/struggling to come out of the traditional relational model.
Let me take the simple Subjects vs Materials
Am trying out the following model,
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Subjects {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
#Persistent
private List<Materials> materials;
}
public class Materials{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String id;
#Persistent
private String materialName;
#Persistent
private String author;
#Persistent
private String materialType;
#Persistent
private String url;
}
When i try to save the materials first and then assigning that object into subjects is having issues. As i read, you cannot assign the child to a parent which is already persisted without parent.
Sometimes it is possible to add materials without assigned to the Subjects, but can get assigned later on.
if you want to make a many-to-many relationship with GAE and JDO you have to store a list of the keys in the models.
User Model
import java.util.Set;
import com.google.appengine.api.datastore.Key;
#PersistenceCapable
public class User {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private Set<Key> courses;
}
Courses Model
import java.util.Set;
import com.google.appengine.api.datastore.Key;
#PersistenceCapable
public class Courses {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private Set<Key> users;
}
this way you don't need the UserCourses class.
EDIT:
If you use
#Persistent
private List<Materials> materials;
you work with a owned relationship model.
this way you can not persist the model first and then add this to the subject model and the persist the subject model.
Just add the not persistent material to the materials list of the subject model and persist the subject model. this will also save the materials.
maybe I could the question wrong but I hope this helps.
I have a parent class and I want to store a HashMap within it. However, every time I try to modify that HashMap I get the following error:
PM org.datanucleus.store.appengine.MetaDataValidator checkForIllegalChildField
WARNING: Unable to validate one-to-many relation com.monsters.server.MonUser.monsters
Any idea what that's about? Here is the code:
This is the code to the Parent class
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class MonUser {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent(serialized="true", mappedBy = "owner")
#Element(dependent = "true")
private HashMap<String,Monster> monsters;
...
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Monster {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private MonUser owner;
...
I've tried everything on the appengine page on relationships and nothing seems to help. Any info would be extremely helpful!
P.S. I've gotten it to work with ArrayLists and the like but not hashmaps, hashtables, maps, etc. If that helps at all.
Only the following Collections are supported by JDO:
java.util.ArrayList<...>
java.util.HashSet<...>
java.util.LinkedHashSet<...>
java.util.LinkedList<...>
java.util.List<...>
java.util.Set<...>
java.util.SortedSet<...>
java.util.Stack<...>
java.util.TreeSet<...>
java.util.Vector<...>
You can persist a HashMap with:
#Persistent(serialized = "true", defaultFetchGroup="true")
see JDO - HashMap within an embedded Class
To ensure persistence of changes you need to always create a new instance of HashMap see the end of:
http://gae-java-persistence.blogspot.de/2009/10/serialized-fields.html