ZK With MongoDB Part 2 - Using Morphia"
m (Created page with "{{Template:Smalltalk_Author| |author=Ashish Dasnurkar, Engineer, Potix Corporation |date=January 18, 2011 |version=ZK 5 }} {{Template:UnderConstruction}} =Introduction= [http:...") |
m |
||
Line 79: | Line 79: | ||
<br /> <br /> | <br /> <br /> | ||
− | Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation | + | Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation; |
+ | |||
+ | <source lang="java"> | ||
+ | public class TaskDAO extends BasicDAO<Task, ObjectId> { | ||
+ | |||
+ | public TaskDAO(Mongo mongo, Morphia morphia) { | ||
+ | super(mongo, morphia, "todo"); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | As you can see, all it takes is an instance of Morphia and an instance of Mango. Similar to Part 1 we can reuse mango instance by defining a singleton object to contain it. Morphia instance is also recommended to create once and reuse. So I have defined a MangoDBManager singleton class that has 2 static methods to maintain single instance of Mango as well as Morphia as shown below; | ||
+ | |||
+ | <source lang="java"> | ||
+ | |||
+ | public class MongoDBManager { | ||
+ | |||
+ | private static Mongo mongo = null; | ||
+ | private static Morphia morphia = null; | ||
+ | private MongoDBManager() {}; | ||
+ | |||
+ | public static synchronized DB getDB() throws Exception { | ||
+ | if(mongo == null) { | ||
+ | mongo = new Mongo(); | ||
+ | } | ||
+ | return mongo.getDB("test"); | ||
+ | } | ||
+ | public static synchronized Mongo getMongo() throws Exception { | ||
+ | if(mongo == null) { | ||
+ | mongo = new Mongo(); | ||
+ | } | ||
+ | return mongo; | ||
+ | } | ||
+ | public static synchronized Morphia getMorphia() throws Exception { | ||
+ | if(morphia == null) { | ||
+ | mongo = getMongo(); | ||
+ | morphia = new Morphia(); | ||
+ | morphia.mapPackage("org.zkoss.mongodb.model"); | ||
+ | } | ||
+ | |||
+ | return morphia; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | The only other thing notable here is the call to <tt>Morphia#mapPackage(String)</tt> which tells morphia from which Java package model classes are to be mapped to MongoDB. |
Revision as of 07:47, 12 January 2012
Ashish Dasnurkar, Engineer, Potix Corporation
January 18, 2011
ZK 5
Introduction
Part 1 introduced you how to write a non-relation database driven ZK application. In particular, I used mongoDB and its Java driver low level APIs. The problem with that approach was I had to manually convert results returned from Java driver APIs to model Javabean instances. Wouldn't it be better if we could just talk to database in terms on POJOs? Morphia, a type-safe Java library does exactly that. It allows mapping Javabean objects to/from mongoDB. Let see how we can use it in our TODO sample application
Using Morphia
Follow the dependencies documentation to include Morphia in your project. I use maven so I simply included following dependency in my pom.xml
<dependency>
<groupId>com.google.code.morphia</groupId>
<artifactId>morphia</artifactId>
<version>0.99</version>
</dependency>
View
View part remains the same as in Part 1. Only change is I have a new controller to use morphia for managing task CRUD operations.
<window title="To do list" width="640px" border="normal" apply="org.zkoss.mongodb.controller.MongoDBMorphiaDemoCtrl">
<listbox id="tasks" multiple="true" rows="10">
<listhead>
<listheader label="Item" />
<listheader label="Priority" width="50px" />
<listheader label="Date" width="90px" />
</listhead>
</listbox>
<groupbox>
<caption label="Event" />
Item: <textbox id="name" constraint="no empty" cols="25" />
Priority: <intbox id="priority" cols="1" constraint="no empty"/>
Date: <datebox id="date" cols="8" constraint="no empty"/>
<button id="add" label="Add" />
<button id="update" label="Update" />
<button id="delete" label="Delete" />
</groupbox>
</window>
Model
Like Hibernate, Morphia uses annotations for defining mapping between POJO and MongoDB document templates. Below I annotate Task Javabean properties with Morphia annotations
@Entity("tasks")
public class Task {
@Id
private ObjectId id;
@Indexed(value = IndexDirection.ASC, name = "taskName", unique = true)
private String name;
@Indexed(value = IndexDirection.ASC, name = "taskPriority")
private int priority;
@Indexed(value = IndexDirection.ASC, name = "executionDate")
private Date executionDate;
// getters and setters
}
Here Entity annotation defines mongoDB collection in which Task Javabean will be stored. Id annotation marks a field in an @Entity to be the id field in mongoDB. MongoDB will auto assign a unique id into it. Indexed annotation defines Javabean property is to be indexed. More on Morphia annotations, refer to here.
Now, as in Part 1 we need a DAO to make persistence calls to MongoDB as it is a good practice to encapsulate persistence calls within DAO so that calling code (controller in this case) can use it without knowing the underlying details. Morphia has a built-in support for DAO interface in the form of BasicDAO implementation of it. This abstract class implements all the basic CRUD methods on model objects. I can just extend from this BasicDAO and since it uses generics to define a parameter class I wouldn't even need to cast the results returned from this DAO methods. Below is my TaskDAO implementation;
public class TaskDAO extends BasicDAO<Task, ObjectId> {
public TaskDAO(Mongo mongo, Morphia morphia) {
super(mongo, morphia, "todo");
}
}
As you can see, all it takes is an instance of Morphia and an instance of Mango. Similar to Part 1 we can reuse mango instance by defining a singleton object to contain it. Morphia instance is also recommended to create once and reuse. So I have defined a MangoDBManager singleton class that has 2 static methods to maintain single instance of Mango as well as Morphia as shown below;
public class MongoDBManager {
private static Mongo mongo = null;
private static Morphia morphia = null;
private MongoDBManager() {};
public static synchronized DB getDB() throws Exception {
if(mongo == null) {
mongo = new Mongo();
}
return mongo.getDB("test");
}
public static synchronized Mongo getMongo() throws Exception {
if(mongo == null) {
mongo = new Mongo();
}
return mongo;
}
public static synchronized Morphia getMorphia() throws Exception {
if(morphia == null) {
mongo = getMongo();
morphia = new Morphia();
morphia.mapPackage("org.zkoss.mongodb.model");
}
return morphia;
}
}
The only other thing notable here is the call to Morphia#mapPackage(String) which tells morphia from which Java package model classes are to be mapped to MongoDB.