Simplifying Persistence for Java and MongoDB with Morphia

63
Engineering Manager, 10gen Jeff Yemin #MongoBoston Morphia: Simplifying Persistence for Java and MongoDB

description

Interested in learning more about MongoDB? Sign up for MongoSV, the largest annual user conference dedicated to MongoDB. Learn more at MongoSV.com

Transcript of Simplifying Persistence for Java and MongoDB with Morphia

Page 1: Simplifying Persistence for Java and MongoDB with Morphia

Engineering Manager, 10gen

Jeff Yemin

#MongoBoston

Morphia: Simplifying Persistence for Java and MongoDB

Page 2: Simplifying Persistence for Java and MongoDB with Morphia

MongoDB on the JVM

• MongoDB Java Driver– Map-based API

• JVM language integrations– Casbah (Scala)– Jmongo (Ruby)– Monger (Clojure)

• ODM (Object Document Mapper)– Morphia– Spring Data MongoDB

Page 3: Simplifying Persistence for Java and MongoDB with Morphia

Morphia

• Object Document Mapper– Specifed with annotations– Implemented with reflection

• Fluent query and update APIs– Runtime validation

Page 4: Simplifying Persistence for Java and MongoDB with Morphia

Morphia by Example

• Model

• Test

• Output

Page 5: Simplifying Persistence for Java and MongoDB with Morphia

<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.8.0</version></dependency>

<dependency> <groupId>com.google.code.morphia</groupId> <artifactId>morphia</artifactId> <version>0.99</version></dependency>

Dependencies

Page 6: Simplifying Persistence for Java and MongoDB with Morphia

<repository> <id>morphia</id> <name>Morphia</name> <url>http://morphia.googlecode.com/svn/mavenrepo/</url> <layout>default</layout></repository>

Repository

Page 7: Simplifying Persistence for Java and MongoDB with Morphia

Morphia morphia = new Morphia();Mongo mongo = new Mongo();Datastore ds = morphia.createDatastore(mongo, "test");

Create the Datastore

Page 8: Simplifying Persistence for Java and MongoDB with Morphia

Entity Modelling

Page 9: Simplifying Persistence for Java and MongoDB with Morphia

Let's model github

Page 10: Simplifying Persistence for Java and MongoDB with Morphia

class Programmer { String name;}

First Entity (model)

Page 11: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";

ds.save(programmer);

First Entity (test)

Page 12: Simplifying Persistence for Java and MongoDB with Morphia

> db.Programmer.findOne(){

"_id" : ObjectId("503292d51aa814c051554696"),"className" : "demo.Programmer","name" : "Scott Hernandez"

}

First Entity (shell)

Page 13: Simplifying Persistence for Java and MongoDB with Morphia

class Programmer { @Id ObjectId id; String name; public void toString() {…}}

@Id (model)

Page 14: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";

ds.save(programmer);System.out.println(programmer)

@Id (test)

Page 15: Simplifying Persistence for Java and MongoDB with Morphia

Programmer{id=5032935f1aa8a8aa3485b441, name='Scott Hernandez'}

@Id (toString)

Page 16: Simplifying Persistence for Java and MongoDB with Morphia

class Programmer { @Id String githubUserName; String name;}

String Id (model)

Page 17: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name= "Scott Hernandez";

ds.save(programmer);

String Id (test)

Page 18: Simplifying Persistence for Java and MongoDB with Morphia

> db.Programmer.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","name" : "Scott Hernandez"

}

String Id (shell)

Page 19: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("programmers")class Programmer { @Id String githubUserName; String name;}

@Entity (model)

Page 20: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","name" : "Scott Hernandez"

}

@Entity (shell)

Page 21: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers;}

More primitives (model)

Page 22: Simplifying Persistence for Java and MongoDB with Morphia

Programmer scott = new Programmer();scott.userName = "scotthernandez";scott.name = "Scott Hernandez";scott.since = dateFmt.parse("Aug 12, 2009");scott.active = true;scott.followers = 8;

ds.save(scott);

More primitives (test)

Page 23: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","name" : "Scott Hernandez","memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"followers" : 8

}

More primitives (shell)

Page 24: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers; List<String> following;}

Primitive Array (Model)

Page 25: Simplifying Persistence for Java and MongoDB with Morphia

Programmer scott = new Programmer();scott.userName = "scotthernandez";scott.name = "Scott Hernandez";scott.since = dateFmt.parse("Aug 12, 2009");scott.active = true;scott.followers = 8;scott.following = Arrays.asList("moraes", "stickfigure");

ds.save(scott);

Primitive Array (test)

Page 26: Simplifying Persistence for Java and MongoDB with Morphia

db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","name" : "Scott Hernandez","memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"followers" : 8,"following" : [

"moraes","stickfigure"

]}

Primitive Array (shell)

Page 27: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("programmers")class Programmer { @Id String githubUserName; Name name; Date memberSince; boolean active; int followers; List<String> following;}

@Embeddedclass Name { String first, last;}

@Embedded (model)

Page 28: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = new Name("Scott", "Hernandez");programmer.memberSince = dateFmt.parse("Aug 12, 2009");programmer.active = true;programmer.followers = 8;programmer.following = Arrays.asList("moraes", "stickfigure");

ds.save(programmer);

@Embedded (test)

Page 29: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","name" : {

"first" : "Scott","last" : "Hernandez"

},"memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"followers" : 8,"following" : [

"moraes","stickfigure"

]}

@Embedded (shell)

Page 30: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("programmers")class Programmer { @Id String githubUserName; Name name; Date memberSince; boolean active; int followers; List<String> following; List<Repository> repositories;}

@Embeddedclass Name { String first, last;}

@Embeddedclass Repository { String name; String forkedFrom;}

@Embedded List (model)

Page 31: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = new Name("Scott", "Hernandez");programmer.memberSince = dateFmt.parse("Aug 12, 2009");programmer.active = true;programmer.followers = 8;programmer.following = Arrays.asList("moraes", "stickfigure");programmer.repositories = Arrays.asList( new Repository("docs", "mongodb/docs"), new Repository("mongo-java-driver", "mongodb/mongo-java-driver"));

ds.save(programmer);

@Embedded (test)

Page 32: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer",…"repositories" : [

{"name" : "docs","forkedFrom" : "mongodb/docs"

},{

"name" : "mongo-java-driver","forkedFrom" : "mongodb/mongo-java-

driver"}

]}

@Embedded List (shell)

Page 33: Simplifying Persistence for Java and MongoDB with Morphia

@Entity("repos")class Repository { @Id ObjectId id; @Reference Programmer owner; String name; String forkedFrom;}

@Reference (model)

Page 34: Simplifying Persistence for Java and MongoDB with Morphia

Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = new Name("Scott", "Hernandez");programmer.memberSince = dateFmt.parse("Aug 12, 2009");programmer.active = true;programmer.followers = 8;programmer.following = Arrays.asList("moraes", "stickfigure");

ds.save(programmer);

Repository repo = new Repository(programmer, "docs", "mongodb/docs");

ds.save(repo);

@Reference (test)

Page 35: Simplifying Persistence for Java and MongoDB with Morphia

> db.repos.findOne(){

"_id" : ObjectId("503297e31aa8255abe542aaa"),"className" : "demo.Repository","owner" : DBRef("programmers", "scotthernandez"),"name" : "docs","forkedFrom" : "mongodb/docs"

}

@Reference (shell)

Page 36: Simplifying Persistence for Java and MongoDB with Morphia

abstract class Member { @Id String userName; @Property("memberSince") Date since; boolean active; String name;}

@Entity("programmers")class Programmer extends Member { int followers; List<String> following;}

@Entity("orgs")class Organization extends Member {}

@Entity("repos")class Repository { @Id ObjectId id; @Reference Member owner; String name; @Reference(lazy=true) Repository forkedFrom;}

Small schema change (model)

Page 37: Simplifying Persistence for Java and MongoDB with Morphia

Programmer scott = new Programmer();//…ds.save(scott);

// save mongodb OrganizationOrganization mongodb = new Organization("mongodb", "mongodb", sdf.parse("Jan 8, 2009"));ds.save(mongodb); // save mongodb's docs RepositoryRepository mongoDocs = new Repository(mongodb, "docs");ds.save(mongoDocs);

// save Scott's forked docs RepositoryRepository scottDocs = new Repository(scott, "docs", mongoDocs);ds.save(scottDocs);

Small schema change (test)

Page 38: Simplifying Persistence for Java and MongoDB with Morphia

> db.orgs.findOne(){

"_id" : "mongodb","className" : "demo.Organization","memberSince" : ISODate("2009-01-08T05:00:00Z"),"active" : false,"name" : "mongodb"

}> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"name" : "Scott Hernandez"

…}

Small schema change (shell)

Page 39: Simplifying Persistence for Java and MongoDB with Morphia

> db.repos.find().toArray()[

{"_id" : ObjectId("503298be1aa8b1d255e5d45b"),"className" : "demo.Repository","owner" : DBRef("orgs", "mongodb"),"name" : "docs"

},{

"_id" : ObjectId("503298be1aa8b1d255e5d45c"),"className" : "demo.Repository","owner" : DBRef("programmers",

"scotthernandez"),"name" : "docs","forkedFrom" : DBRef("repos",

ObjectId("503298be1aa8b1d255e5d45b"))}

]

Small schema change (shell, 2)

Page 40: Simplifying Persistence for Java and MongoDB with Morphia

Querying

Page 41: Simplifying Persistence for Java and MongoDB with Morphia

Find by Equality (test)

• ds.get(Programmer.class, "scotthernandez")

• ds.find(Programmer.class, "userName", "scotthernandez")

• ds.find(Programmer.class).field("userName").equal("scotthernandez”)

Page 42: Simplifying Persistence for Java and MongoDB with Morphia

Find by Equality (logs)

• test.programmers query: { _id: "scotthernandez" }

• test.programmers query: { userName: "scotthernandez" }

• test.programmers query: { userName: "scotthernandez" }

Page 43: Simplifying Persistence for Java and MongoDB with Morphia

Find by Range (test)

• ds.find(Programmer.class).field("followers").greaterThan(0)

• ds.find(Programmer.class).filter("followers >", 0)

• ds.find(Programmer.class).field("since"). lessThan(sdf.parse("Jan

1, 2010"))

Page 44: Simplifying Persistence for Java and MongoDB with Morphia

Find by Range (logs)

• test.programmers query: { followers: { $gt: 0 } }

• test.programmers query: { followers: { $gt: 0 } }

• test.programmers query: { memberSince: { $lt: new

Date(1262322000000) } }

Page 45: Simplifying Persistence for Java and MongoDB with Morphia

ds.find(Programmer.class).

field("since").lessThan(dateFmt.parse("Jan 1, 2010")).field("followers").greaterThan(0)

Combining conditions (test)

Page 46: Simplifying Persistence for Java and MongoDB with Morphia

test.programmers query: { memberSince: { $lt: new Date(1262322000000) }, followers: { $gt: 0 } }

Combining conditions(logs)

Page 47: Simplifying Persistence for Java and MongoDB with Morphia

Programmer scott = new Programmer("scotthernandez")ds.find(Repository.class).field("owner").equal(scott)

Find by Reference (test)

Page 48: Simplifying Persistence for Java and MongoDB with Morphia

test.repos query: { owner: { $ref: "programmers", $id: "scotthernandez" } }

Find by Reference (logs)

Page 49: Simplifying Persistence for Java and MongoDB with Morphia

Indexing

Page 50: Simplifying Persistence for Java and MongoDB with Morphia

@Indexed

• Annotation for fields– value (IndexDirection)– name (String)– unique (boolean)– dropDups (boolean)– background (boolean)– sparse (boolean)

• Examples– @Indexed(value=IndexDirection.ASC,

name="followers") int followers;– @Indexed @Reference(lazy = true) Repository

forkedFrom;

Page 51: Simplifying Persistence for Java and MongoDB with Morphia

@Indexes and @Index

• @Indexes: Annotation for types– value (Index[])

• @Index– value (String)– Others same as @Indexed

• Examples– @Indexes(@Index("since, -followers")) public class

Programmer {…}

Page 52: Simplifying Persistence for Java and MongoDB with Morphia

Updating

Page 53: Simplifying Persistence for Java and MongoDB with Morphia

Programmer jeff = createJeff();ds.save(jeff);

// jeff is following scott, so increment // scott's followers and re-saveProgrammer scott = ds.get(Programmer.class, "scotthernandez")

scott.followers++;ds.save(scott);

Updating with save (test)

Page 54: Simplifying Persistence for Java and MongoDB with Morphia

update test.programmers

query: { _id: "scotthernandez", } update: { _id: "scotthernandez", className: "demo.Programmer", followers: 9, following: [ "moraes", "stickfigure" ], memberSince: new Date(1250049600000), active: true, name: "Scott Hernandez", }

Updating with save (logs)

Page 55: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","followers" : 9,"following" : [

"moraes","stickfigure"

],"memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"name" : "Scott Hernandez"

}

Updating with save (shell)

Page 56: Simplifying Persistence for Java and MongoDB with Morphia

@Entitypublic abstract class Member { @Id String userName; @Property("memberSince") Date since; boolean active; String name; @Version Long version;}

Optimistic Concurrency (model)

Page 57: Simplifying Persistence for Java and MongoDB with Morphia

update test.programmers

query: { _id: "scotthernandez", version: 1345497713173 } update: { _id: "scotthernandez", className: "demo.Programmer", followers: 9, following: [ "moraes", "stickfigure" ], memberSince: new Date(1250049600000), active: true, name: "Scott Hernandez", version: 1345497718181 }

Optimistic Concurrency (logs)

Page 58: Simplifying Persistence for Java and MongoDB with Morphia

> db.programmers.findOne(){

"_id" : "scotthernandez","className" : "demo.Programmer","followers" : 9,"following" : [

"moraes","stickfigure"

],"memberSince" : ISODate("2009-08-12T04:00:00Z"),"active" : true,"name" : "Scott Hernandez","version" : NumberLong("1345497718181")

}

Optimistic Concurrency (shell)

Page 59: Simplifying Persistence for Java and MongoDB with Morphia

Programmer jeff = createJeff();ds.save(jeff);

// increment followers of scott by oneUpdateOperations<Programmer> incrementFollowing = ds.createUpdateOperations(Programmer.class). inc("followers", 1);

Query<Programmer> queryForScott = ds.find(Programmer.class, "userName", "scotthernandez");

ds.update(queryForScott, incrementFollowing);

UpdateOperations (test)

Page 60: Simplifying Persistence for Java and MongoDB with Morphia

update test.programmers

query: { _id: "scotthernandez" }

update: { $inc: { followers: 1 } }

UpdateOperations (logs)

Page 61: Simplifying Persistence for Java and MongoDB with Morphia

Web Resources

• Morphia home: http://code.google.com/p/morphia/

• Morphia user group: https://groups.google.com/forum/?fromgroups#!forum/morphia

• Demo code: https://github.com/jyemin/morphia-demo

– Separate commit and tag for each slide, so you can play along

Page 62: Simplifying Persistence for Java and MongoDB with Morphia

Thanks!

• Jeff Yemin– https://twitter.com/@jeffyemin– [email protected]– https://github.com/jyemin/

Page 63: Simplifying Persistence for Java and MongoDB with Morphia

Engineering Manager, 10gen

Jeff Yemin

#MongoBoston

Thank You