Java ORMs for MongoDB

Some time ago I wrote a post covering a combination of Spring Data and MongoDB in action. That post was demonstrating how incredibly convenient and deadly simple the data persistence can be implemented with the combination of MongoDB and Spring Data. Thinking on this matter for a while, I released that my post was somewhat unfair in regards to the other ORMs compatible with MongoDB. After all, the concept of mapping domain objects into DB structures and vice versa does not belong to Spring Data exclusively and is widely known as ORM paradigm. Furthermore, unlike with RDBMSes where usage of ORM in your application is somewhat controversial and should be applied with caution, MongoDB already stores data as documents so it’s not a crime to simplify life of developers allowing to make data persistence as easy and as smooth as possible.

Long story short, I would like to introduce a list of ORMs which I know can work with MongoDB. I’m also going to partially cover some pros and cons of using each and the stage on which each project happened to be at the moment of writing. (The most viable options from my point of view will appear in the top of the list).

1) Spring Data for MongoDB is a project under Spring umbrella which is meant to simplify the development of Java applications for Mongo. Key features are a seamless integration with Spring Framework, dynamic repository facility for rapid development, a complete ORM solution(unlike Spring JDBC Template), frequent releases and Spring community support.

2) Morphia is a very stable and feature-rich ORM designed explicitly for MongoDB. Has some nice documentation and google group filled with responses to a huge number of questions. Unfortunately the version on Google Code seems to be abandoned by the original author which means that the newest Mongo features are not going to appear in the ORM(like Aggregation Framework and some new query keywords).

There is fork of Morphia on GitHub – https://github.com/jmkgreen/morphia which has some activity around it. So hopefully this ORM can survive and evolve.

3) The next option is Jongo which is also a kind of ORM written in Java. The most attractive features are the performance promised by developers and convenience of having queries identical to Mongo Shell(JavaScript-based) in your Java code. The project is also kept on GitHub and seems to have a quite vibrant community.

4) Here is also a number of JPA 2.0 providers which support MongoDB. EclipseLink, Kundera and DataNucleus to name a few. The major advantage in this case is that you can program to a familiar JPA interface/annotations, but on the other side you may not be able to do thing which require your code to be more “Mongo-specific”(e.g. specify WriteConcern etc.). For more details you should look in the documentation of each product. For people interested in examples I add a link with EclipseLink in action and a link about Kundera.

5) Hibernate OGM is the next framework in the list which is inspired by the popular Java ORM Hibernate. By the time of writing the latest version is 4.0.0.Beta2 and the development process seems to be somewhat stale(no activity for two months). A post showing it in action can be found by the following link. But until the version gets more stable I wouldn’t suggest using it seriously.

6) And there is also MJORM which lacks documentation(at least at Google Code) but can also be considered as an alternative. Its most interesting feature is a query language similar to SQL.

As far as you can see there is a number of alternatives you can choose between, but the best option should always be chosen depending on your business requirements, available time and familiarity with certain technologies. Good luck!

Advertisements

MongoDB with Spring Data – Awesome combination for a social game

In my previous post “Considerations for choosing or not choosing MongoDB” I covered some pros and cons of choosing MongoDB as a primary storage for your project. Today I’m going to demonstrate how MongoDB and Spring Data can be applied to development of a social game, extremely simplifying the development and providing really outstanding results.

Please note, that this article would in fact fit any solution which is similar in data access pattern to a social game. I’ll be discussing more details on this matter in the next section.

What is a social game?

A social game is basically a type of online game where players mostly interact with their own game areas(e.g. player’s farm) and use a social network in order share their achievements and ask friends for help. So the most common data access pattern in the game is retrieving or updating data by some kind of user identifier. Here are the key requirements which any typical social game would have to meet:

  1. Most optimal performance for the common data access operations(players don’t like to wait);
  2. Horizontal scaling is a must because you will need to get quite a lot of users before your game starts making profit;
  3. At some point you would definitely need add some analytics and more sophisticated features(e.g. showing top 5 players in the neighbourhood);
  4. Rapid prototype development and ability to add new features quickly(i.e. minimizing time to market and applying “fail fast” principal).

Domain Model

Any program written in object oriented language contains domain model classes which represent the domain of the problem the application is meant to solve. In our particular case we are going to review the domain model of our social game. Here is the class diagram build by IntelijjIDEA:

social_game_classes_diagramAs far as you can see, the root of our class hierarchy is UserModel which in addition to its fields-primitives contains a list of Achievements and a reference to UserFarm object. A instance of UserFarm would then contain a reference to its coordinates, a list of buildings and some other fields. The last detail worth noticing is that UserFarm contains a list Building objects which might be both instances of Building as well as instances of CropsBuilding.

You can find the exact classes by the following link in a GitHub repo.

How it might look in the relational world.

Before I show you how MongoDB and SpringData can be used for persistence of our domain model, let’s dive into the world of relational databases, and see how our ER diagram would look like. Here it goes:

social_game_er_diagramAs far as you can see, there are 6 tables in this model. Whenever a new user registers you will need to fill them with new rows, and then select all the data on each user’s visit and then update certain rows after game activities. Even having ORM and caching in place won’t protect you from possible performance/scalability issues, and all the time you would spend fighting for performance and re-designing your ER schema could be spent on new features and user experience improvements.

Spring Data and MongoDB in Action

Setting up Spring Data for MongoDB in your project is quite simple and can be done as follows:

1) Add dependencies on Spring, Mongo Java Driver and Spring Data MongoDB into your project. (See the sample pom.xml)

2) Create your DAO interface and extend Spring Data’s CrudRepository interface. You won’t even need to implement your DAO because Spring will generate an implementation in runtime.

3) Add a Spring configuration class looking like this:

@Configuration
@EnableMongoRepositories(basePackages = "org.simple.farm.dao")
@ComponentScan("org.simple.farm.dao")
public class SimpleFarmConfiguration {

    @Bean
    public MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new Mongo(), "farm");
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
        return mongoTemplate;

    }
}

Now you are ready to save/find your data in MongoDB. Here is some code which would insert a new user into DB:

final String username = "testUserName";
UserFarm userFarm = UserFarmBuilder.createFarmBuilder("Test Farm", 15, 15).
        setResources(90, 130, 150).addCropsBuilding(1, 0, 0, new Date()).
        addSimpleBuilding(Building.BuildingType.SCARE_CROW, 1, 1, 1).build();
userDao.save(UserModelBuilder.createUserBuilder(username, "a password", new Date())
        .setFarm(userFarm).setExperience(0).addAchievement(Achievement.AchievementType.BUILDER, 1)
        .build());

The result of execution can be verified from the Mongo Shell:


> db.userModel.findOne()
{
	"_id" : ObjectId("513b6e1c84ae21612fafe599"),
	"_class" : "org.simple.farm.model.UserModel",
	"login" : "testUserName",
	"password" : "a password",
	"registered" : ISODate("2013-03-09T17:15:08.515Z"),
	"achievements" : [
		{
			"type" : "BUILDER",
			"level" : 1
		}
	],
	"experience" : NumberLong(0),
	"farm" : {
		"name" : "Test Farm",
		"location" : {
			"x" : 15,
			"y" : 15
		},
		"level" : 1,
		"food" : 90,
		"stone" : 130,
		"wood" : 150,
		"buildings" : [
			{
				"lastHarvest" : ISODate("2013-03-09T17:15:08.513Z"),
				"inFarmLocation" : {
					"x" : 0,
					"y" : 0
				},
				"level" : 1,
				"type" : "CROPS",
				"_class" : "org.simple.farm.model.embedded.CropsBuilding"
			},
			{
				"inFarmLocation" : {
					"x" : 1,
					"y" : 1
				},
				"level" : 1,
				"type" : "SCARE_CROW"
			}
		]
	}
}

Full source code of this example can be found in the GitHub repo.

As far as you can see, the persistence of your domain model has never been so easy. Nested arrays and objects fit perfectly into Mongo and Spring Data removes any need in manually creating DBObjects and allows to focus on your business requirements in the first place.

Other advantages of MongoDB

Besides easiness in development of simple CRUD operations for your domain objects, there are certain features of MongoDB which can turn out to be quite handy:

  1. Easy schema migrations. Since your objects are not just arrays of bytes to DB, you can use the power of MongoDB querying facility while writing DB-migration scripts.
  2. Geospatial Idexes can be quite useful in order to find neighbours of a player.
  3. Aggregation Framework is nice for ad-hoc analytics which otherwise would require setting up an RDBMS to run your queries on.

Summary

If you have read this far you can see why I said that Spring Data and MongoDB can be an awesome combination for certain types of applications. Hope you enjoyed the reading!