Purchase Management System – Data model

Hello,
and Welcome to the third episode of the pms crime-thriller :D
As promised, today we will discribe and discuss the main data model design and maybe take a first look at Google App Engine especially its support for persistency.
Figure 1 shows the main datamodel of the backend of PMS. What we see are four main entities called GROUP, MEMBER, PURCHASE and ITEM and one relational table called PARTICIPANTS.

pms data model

Figure 1: PMS Data-Model

As mentioned in the previous post i will NOT use JDBC for making data persistent. Instead of this, lets take the modern object orientated path by using the GAE implementation of the JDO specification. As an alternative one could also make use of the Java Persistence Api (JPA) but i already used JPA (especially Toplink JPA) in my previous project and i am just snoopy about JDO now. Lets take a closer look at the data model:

GROUP
A group specifies a set of people (members) who are in the same community. Each group is uniquely identifiable through an ID. Making Entities unique through an ID is always a better idea instead of identify it, say, through the name (i.e. isn’t it annoying when a system is restricted in such a way that users are not able to change their usernames or have the same username? ) So all entities in pms are identifiable through an ID value. In fact we will not have to bother about these ID’s because JDO will do the work for us ;)

MEMBER
This entity stays in relation with the previously discussed group entity. There is not very much to say about this entity. Members are the users who are gonna use the system and are just insiders of one or more groups.

There’s one important thing to mention about the GROUP <–> MEMBER relation. These entities are related through a M:N relation, i.e. various members can be insider of several groups. My first idea was to have a simple 1:n relation between those entities but i think this would be an annoying restriction for later and it would be a bunch of work to change this in future when the whole system is running. So Members can not only be inside of just ONE group. They can be in thousands over thousands of groups :D

PURCHASE
As the name may say this entity represents a purchase of a member at a noticed time. It stays in relation with a bunch of items (articles) and is also one core entity of the system.

ITEM
This entity represents a product or article which one member buys on his shopping, and it point to a several purchase through a 1:n relation.

PARTICIPANTS
This is just a “purchase2member” table which links the purchase to its participants. As you can think it’s not always the case that each purchase is assigned to each member of the group. So users must have the opportunity to choose between the participants of the current purchase.

Now, that we have discussed the main entities of the datamodel we have to talk about JDO, its features and restrictions.
JDO differs between “owned relationships” where one of the objects cannot exist without the other  and “unowned relationships” where both objects can exist independently of their relationship with one another.
Unfortunately the App Engine implementation of JDO does not yet implement this facility of unowned relations, but there’s a workaround. But first i will explain how Objects can be persisted via JDO.
Lets take a look at a codesnippet from the Purchase entity:

import java.util.Date;
import java.util.List;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;

@PersistenceCapable
public class Purchase {


...
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
private List<Item> items;

@Persistent
private Member member;

@Persistent
private Date date;

}
...

As you can see each JDO entity has to be annotated with the @PersistenceCapable annotation and each field which shall be persisted depends on a @Persistent annotation. JDO can generate and handle unique identifier with the Key object so one can rely on this :) . Moreover this entity is an “owned” one. In other words it has an 1:n relation with the member entity because it holds a private field of the Member type. If we want to create an “unowned” relationship this is, as previously mentioned, just possible through a special way. You can still manage these relationships using Key values in place of instances (or Collections of instances) of your model objects. You can think of storing Key objects as modeling an arbitrary “foreign key” between two objects. We make use of this “workaround” for example in our Member entity where it holds an Set of keys, which will be the keys of the Groups.

...
@PersistenceCapable
public class Member {

@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;

@Persistent
private Set<Key> groups;

@Persistent
private String uname;

@Persistent
private String password;
...

Important: JDO or the compiler will not do any kind of type checking for you. So your application has to take care of it. The application has also as to take care of both sides of the Key collections in a M:N relation !!!

GAE JDO restrictions: As you can read here JDO is not completely implemented in GAE.  For example JOINS are not supported. I don’t know how far this restriction would affect the development process. We will see!

The next tasks will be to finish the entity creations and to take a look how we can actually store this data to the datastore.

For now, have a good day and see you in my next post. :)

bernd

, , ,
  • Delicious
  • Facebook
  • Digg
  • Reddit
  • StumbleUpon
  • Twitter

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>