Morphia: Simplifying Persistence for Java and MongoDB

on

  • 8,208 views

 

Statistics

Views

Total Views
8,208
Views on SlideShare
7,366
Embed Views
842

Actions

Likes
10
Downloads
58
Comments
0

10 Embeds 842

http://jmchung.github.io 691
http://localhost 106
https://twitter.com 18
https://si0.twimg.com 18
http://www.twylah.com 3
http://gazeta.yandex.ru 2
https://twimg0-a.akamaihd.net 1
http://bottlenose.com 1
http://embed.ly 1
http://fiddle.jshell.net 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Morphia:  Simplifying Persistence for Java and MongoDB Morphia: Simplifying Persistence for Java and MongoDB Presentation Transcript

  • MorphiaSimplifying Persistence for Java and MongoDB Jeff Yemin
  • Outline• MongoDB• MongoDB on the JVM• Morphia by Example – Model – Test – Output
  • MongoDB• Document-oriented storage – JSON-style documents• Rich, document-based queries• Full index support• Fast in-place updates• Convenient Javascript shell• Customer drivers for all major language
  • 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
  • Morphia• Object Document Mapper – Specifed with annotations – Implemented with reflection• Fluent query and update APIs – Runtime validation
  • Dependencies<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>
  • Repository<repository> <id>morphia</id> <name>Morphia</name> <url>http://morphia.googlecode.com/svn/mavenrepo/</url> <layout>default</layout></repository>
  • Create the DatastoreMorphia morphia = new Morphia();Mongo mongo = new Mongo();Datastore ds = morphia.createDatastore(mongo, "test");
  • Lets model github
  • First Entity (model)class Programmer { String name;}
  • First Entity (test)Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";ds.save(programmer);
  • First Entity (shell)> db.Programmer.findOne(){ "_id" : ObjectId("503292d51aa814c051554696"), "className" : "demo.Programmer", "name" : "Scott Hernandez"}
  • @Id (model)class Programmer { @Id ObjectId id; String name; public void toString() {…}}
  • @Id (test)Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";ds.save(programmer);System.out.println(programmer)
  • @Id (toString)Programmer{id=5032935f1aa8a8aa3485b441, name=Scott Hernandez}
  • String Id (model)class Programmer { @Id String githubUserName; String name;}
  • String Id (test)Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name= "Scott Hernandez";ds.save(programmer);
  • String Id (shell)> db.Programmer.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", "name" : "Scott Hernandez"}
  • @Entity (model)@Entity("programmers")class Programmer { @Id String githubUserName; String name;}
  • @Entity (shell)> db.programmers.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", "name" : "Scott Hernandez"}
  • More primitives (model)@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers;}
  • More primitives (test)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 (shell)> db.programmers.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", "name" : "Scott Hernandez", "memberSince" : ISODate("2009-08-12T04:00:00Z"), "active" : true, "followers" : 8}
  • Primitive Array (Model)@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers; List<String> following;}
  • Primitive Array (test)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 (shell) 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" ]}
  • @Embedded (model)@Entity("programmers")class Programmer { @Id String githubUserName; Name name; Date memberSince; boolean active; int followers; List<String> following;}@Embeddedclass Name { String first, last;}
  • @Embedded (test)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 (shell)> 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 List (model)@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 (test)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 List (shell)> db.programmers.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", … "repositories" : [ { "name" : "docs", "forkedFrom" : "mongodb/docs" }, { "name" : "mongo-java-driver", "forkedFrom" : "mongodb/mongo-java-driver" } ]}
  • @Reference (model)@Entity("repos")class Repository { @Id ObjectId id; @Reference Programmer owner; String name; String forkedFrom;}
  • @Reference (test)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 (shell)> db.repos.findOne(){ "_id" : ObjectId("503297e31aa8255abe542aaa"), "className" : "demo.Repository", "owner" : DBRef("programmers", "scotthernandez"), "name" : "docs", "forkedFrom" : "mongodb/docs"}
  • Small schema change (model)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 (test)Programmer scott = new Programmer();//…ds.save(scott);// save mongodb OrganizationOrganization mongodb = new Organization("mongodb", "mongodb", sdf.parse("Jan 8, 2009"));ds.save(mongodb);// save mongodbs docs RepositoryRepository mongoDocs = new Repository(mongodb, "docs");ds.save(mongoDocs);// save Scotts forked docs RepositoryRepository scottDocs = new Repository(scott, "docs", mongoDocs);ds.save(scottDocs);
  • Small schema change (shell)> 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, 2)> 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")) }]
  • Find by Equality (test)• ds.get(Programmer.class, "scotthernandez")• ds.find(Programmer.class, "userName", "scotthernandez")• ds.find(Programmer.class).field("userName").equal("scotthernandez")
  • Find by Equality (logs)• test.programmers query: { _id: "scotthernandez" }• test.programmers query: { _id: "scotthernandez" }• test.programmers query: { _id: "scotthernandez" }
  • 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"))
  • Find by Range (logs)• test.programmers query: { followers: { $gt: 0 } }• test.programmers query: { followers: { $gt: 0 } }• test.programmers query: { memberSince: { $lt: new Date(1262322000000) } }
  • Combining conditions (test)ds.find(Programmer.class). field("since").lessThan(dateFmt.parse("Jan 1, 2010")). field("followers").greaterThan(0)
  • Combining conditions (logs)test.programmers query: { memberSince: { $lt: new Date(1262322000000) }, followers: { $gt: 0 }}
  • Find by Reference (test)ds.find(Repository.class).field("owner").equal(scott)
  • Find by Reference (logs)test.repos query: { owner: { $ref: "programmers", $id: "scotthernandez" }}
  • @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;
  • @Indexes and @Index• @Indexes: Annotation for types – value (Index[])• @Index – value (String) – Others same as @Indexed• Examples – @Indexes(@Index("since, -followers")) public class Programmer {…}
  • Updating with save (test)Programmer jeff = createJeff();ds.save(jeff);// jeff is following scott, so increment// scotts followers and re-saveProgrammer scott = ds.get(Programmer.class, "scotthernandez")scott.followers++;ds.save(scott);
  • Updating with save (logs)update test.programmersquery: { _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 (shell)> 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"}
  • Optimistic Concurrency (model)@Entitypublic abstract class Member { @Id String userName; @Property("memberSince") Date since; boolean active; String name; @Version Long version;}
  • Optimistic Concurrency (logs)update test.programmersquery: { _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 (shell)> 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("1345497660444")}
  • UpdateOperations (test)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);
  • 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
  • Boston Resources• MongoDB User Group: http://www.meetup.com/Boston- MongoDB-User-Group/• 10gen office hours: Monthly at Dog Patch (with yours truly)
  • MongoDB Boston• October 23-24 – Oct 23: Workshops on Schema Design and Operations – Oct 24: Conference talks – Discount code: MUG10 for 10% off tickets – Early bird prices end Sept. 24 – Submit a talk proposal at 10gen.com/talk-proposal – URL: 10gen.com/events/mongodb-boston
  • Thanks!• Jeff Yemin – https://twitter.com/@jeffyemin – jeff.yemin@10gen.com – https://github.com/jyemin/