Google App Engine Datastore
Storing and retrieving persistent data on the Datastore is very easy. I’ll walk you through the steps of each.
Set up
Before you can store data, you will need a PersistenceManager (javax.jdo.PersistenceManager). The PersistenceManager implements the singleton pattern (so only one instance can be open at any given time). Google recommends using a singleton wrapper to get the programs PersistenceManager. The following code if found in PMF.class:
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
public final class PMF {
private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");
private PMF() {
}
public static PersistenceManagerFactory get() {
return pmfInstance;
}
}
To use this file, when you need data you will need to get the current instance of it using this code:PersistenceManager pm = PMF.get().getPersistenceManager();
Creating JDOs Now that we have our PMF class, we will need to create an entity bean. An entity bean is a simple Java class with attributes and getters and setters (to get and store data). There are a few special tags that you must remember when creating these beans to use in Google App Engine.
@PersistenceCapable(identityType = IdentityType.APPLICATION)
if you forget this one, you won’t be able to store anything.
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
these are for your primary key. You can generate your own primary keys if you want (use email addresses or whatever) but I generally like to stick with the keys that the datastore provide.
@Persistent
this must go in front of all the attributes you want to store (or the datastore will conveniently forget to store them.
Now lets look at an example: This is a simple class with only two attributes, a Key and a String.
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class FavoriteFood {
//attributes
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String foodName;
//auto generated getters and setters (all are present except setKey() which is unneeded
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public Key getKey() {
return key;
}
}
Setting data Now that we have our PMF class and a JDO to work with, we can now store data. Google App Engine only allows data to be stored programmatically so storing data is essential before retrieval is possible. While there are many ways to store data, I use AJAX to send a request to a FrontController object which forwards all requests to an ApplicationController which determines which class to run. All the classes implement an interface I call Interactor. Click here for information about the FrontController, ApplicationController, and the Iterator.
It is quite simple to store data:
// ... PersistenceManagare pm = PMF.get().getPersistenceManager();
FavoriteFood aFood = new FavoriteFood();
aFood.setFoodName(foodName);
try {
pm.makePersistent(aFood);
} finally {
pm.close();
}
Thats it! You may have to do the logic to check it the Object
you are persisting is valid, but if you want to store something, it’s pretty simple. Editing a persistent Object
is even easier, well … about as easy. But before we can do that, we have to get the FavoriteFood
out of storage (lets hope it keeps well).
Getting persistent data
There are several ways to get an Object
from storage. I’ll show you two methods, if you like SQL you’ll like the first, if you prefer method calls then you’ll like the second. I’ll also show you the method to get an Object
by its Key
.
//... PersistenceManager pm = PMF.get().getPersistenceManager();
try {
// First declare a query String
String query = "select from " + FavoriteFood.class.getName();
// or if you want to filter (don't forget the single quotes around the filter)
String queryFilter = "select from " + FavoriteFood.class.getName() + " where foodName =='" + foodName + "' order by foodName";
// Then use the persistence manager to get the instances of the Object
List foods = (List) pm.newQuery(query).execute();
// then do whatever you want with the results
// you may want to check if the results are empty: if(foods.isEmpty()) {...
// you may want to iterate through the results: for(Food f: foods) {...
} finally {
pm.close();
}
This next approach is even easier.
//... PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = pm.newQuery(FavoriteFood.class);
try {
List foods = query.execute();
} finally {
pm.close();
}
To set filter data run this after you declare the query: query.setFilter("favoriteFood == favoriteFoodVar")
followed by the parameter declaration: query.declareParameters("String favoriteFoodVar")
. When you run the query you will enter the favoriteFoodVar in as a parameter: query.execute("ice cream");
. To set an order to the results, before you run the query type: query.setOrdering("favoriteFood desc");
To get an Object
by its Key
you may need a few things. The KeyFactory
may be helpful. One of its uses is to convert a Key
to a String
and back if necessary. This is helpful with form submission etc.:
//change a Key to a String
String foodKeyString = KeyFactory.keyToString(foodKey);
//change a String to a Key
Key foodKey = KeyFactory.stringToKey(foodKeyString);
Once you have a Key
you can easily get any object using the getObjectById(Class, Key)
method.
// PersistanceManager is open as "pm"
FavoriteFood food = pm.getObjectById(FavoriteFood.class, foodKey);
Editing persistent data
When you have data in the datastore that you want to change, it is very simple. To edit an Object
that is already in the datastore you just need to open the PersistenceManager
and get the object you want to to edit. Once it is open you can just change it: object.setParamName("whatever")
then close the PersistenceManager like normal in the finally
block:
// make sure the PersistanceManager is open
try {
FavoriteFood food = pm.getObjectById(FavoriteFood.class, foodKey);
food.setFoodName("enchiladas");
} finally {
//once the PersistanceManager is closed, the data is made permanent.
pm.close();
}
Deleting data Deleting persistant data is probably one of the easiest thing you can do. Once you have the object you just need to run the deletePersistent(Object o) method
// PersistanceManager is open
try {
FavoriteFood food = pm.getObjectById(FavoriteFood.class, foodKey);
pm.deletePersistent(food);
} finally {
pm.close();
}
Conclusion So now you know how to create data, get that content, edit content, and delete content.
All of this can be found on Google’s Creating, Getting and Deleting Data page, the Defining Data Classes page, or the Queries and Indexes page.