Your SlideShare is downloading. ×
0

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Simplifying Persistence for Java and MongoDB with Morphia

4,746

Published on

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

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

0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,746
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
51
Comments
0
Likes
6
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Builds on the java driver"test" is the name of a database'
  • NameEmilMember SinceFollowersRespositories
  • No annotations. Pure POJO
  • 1. Save will insert or update
  • Collection name defaults to class name_id is generated as an ObjectIdclassName has the full class name, including package. Used for polymorphic collectionCan you query for base class? How?
  • 1. Morphia will generate an id and stuff it in the field annotated with @Id
  • 1. If you already have a unique id, you should use it as your @Id
  • 1. Morphia won't generate these for you
  • 1. If you just use @Entity, it defaults the collection name to the class name.
  • Note the collection name
  • Let's switch it up. Instead of embedding the repos in the programmer, let's have repos as top-level docs that reference owner by key
  • Get by primary keyShortcut for getting by a single propertyLongcut, same as above but extensible
  • 1. Note the weird syntax to make followers descending
  • Note that to update followers, we updated everything…Point out the problems with this
  • Transcript

    • 1. #MongoBostonMorphia: SimplifyingPersistence for Java andMongoDBJeff YeminEngineering Manager, 10gen
    • 2. 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
    • 3. Morphia• Object Document Mapper – Specifed with annotations – Implemented with reflection• Fluent query and update APIs – Runtime validation
    • 4. Morphia by Example• Model• Test• Output
    • 5. 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>
    • 6. Repository<repository> <id>morphia</id> <name>Morphia</name> <url>http://morphia.googlecode.com/svn/mavenrepo/</url> <layout>default</layout></repository>
    • 7. Create the DatastoreMorphia morphia = new Morphia();Mongo mongo = new Mongo();Datastore ds = morphia.createDatastore(mongo, "test");
    • 8. Entity Modelling
    • 9. Lets model github
    • 10. First Entity (model)class Programmer { String name;}
    • 11. First Entity (test)Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";ds.save(programmer);
    • 12. First Entity (shell)> db.Programmer.findOne(){ "_id" : ObjectId("503292d51aa814c051554696"), "className" : "demo.Programmer", "name" : "Scott Hernandez"}
    • 13. @Id (model)class Programmer { @Id ObjectId id; String name; public void toString() {…}}
    • 14. @Id (test)Programmer programmer = new Programmer();programmer.name= "Scott Hernandez";ds.save(programmer);System.out.println(programmer)
    • 15. @Id (toString)Programmer{id=5032935f1aa8a8aa3485b441, name=Scott Hernandez}
    • 16. String Id (model)class Programmer { @Id String githubUserName; String name;}
    • 17. String Id (test)Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name= "Scott Hernandez";ds.save(programmer);
    • 18. String Id (shell)> db.Programmer.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", "name" : "Scott Hernandez"}
    • 19. @Entity (model)@Entity("programmers")class Programmer { @Id String githubUserName; String name;}
    • 20. @Entity (shell)> db.programmers.findOne(){ "_id" : "scotthernandez", "className" : "demo.Programmer", "name" : "Scott Hernandez"}
    • 21. More primitives (model)@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers;}
    • 22. 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);
    • 23. 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}
    • 24. Primitive Array (Model)@Entity("programmers")class Programmer { @Id String githubUserName; String name; Date memberSince; boolean active; int followers; List<String> following;}
    • 25. 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);
    • 26. 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" ]}
    • 27. @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;}
    • 28. @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);
    • 29. @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" ]}
    • 30. @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;}
    • 31. @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);
    • 32. @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" } ]}
    • 33. @Reference (model)@Entity("repos")class Repository { @Id ObjectId id; @Reference Programmer owner; String name; String forkedFrom;}
    • 34. @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);
    • 35. @Reference (shell)> db.repos.findOne(){ "_id" : ObjectId("503297e31aa8255abe542aaa"), "className" : "demo.Repository", "owner" : DBRef("programmers", "scotthernandez"), "name" : "docs", "forkedFrom" : "mongodb/docs"}
    • 36. 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;}
    • 37. 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);
    • 38. 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" …}
    • 39. 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")) }]
    • 40. Querying
    • 41. Find by Equality (test)• ds.get(Programmer.class, "scotthernandez")• ds.find(Programmer.class, "userName", "scotthernandez")• ds.find(Programmer.class).field("userName").equal("scotthernandez”)
    • 42. Find by Equality (logs)• test.programmers query: { _id: "scotthernandez" }• test.programmers query: { userName: "scotthernandez" }• test.programmers query: { userName: "scotthernandez" }
    • 43. 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"))
    • 44. Find by Range (logs)• test.programmers query: { followers: { $gt: 0 } }• test.programmers query: { followers: { $gt: 0 } }• test.programmers query: { memberSince: { $lt: new Date(1262322000000) } }
    • 45. Combining conditions (test)ds.find(Programmer.class). field("since").lessThan(dateFmt.parse("Jan 1, 2010")). field("followers").greaterThan(0)
    • 46. Combining conditions (logs)test.programmers query: { memberSince: { $lt: new Date(1262322000000) }, followers: { $gt: 0 }}
    • 47. Find by Reference (test)Programmer scott = new Programmer("scotthernandez")ds.find(Repository.class).field("owner").equal(scott)
    • 48. Find by Reference (logs)test.repos query: { owner: { $ref: "programmers", $id: "scotthernandez" }}
    • 49. Indexing
    • 50. @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;
    • 51. @Indexes and @Index• @Indexes: Annotation for types – value (Index[])• @Index – value (String) – Others same as @Indexed• Examples – @Indexes(@Index("since, -followers")) public class Programmer {…}
    • 52. Updating
    • 53. 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);
    • 54. 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",}
    • 55. 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"}
    • 56. Optimistic Concurrency (model)@Entitypublic abstract class Member { @Id String userName; @Property("memberSince") Date since; boolean active; String name; @Version Long version;}
    • 57. 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}
    • 58. 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("1345497718181")}
    • 59. 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);
    • 60. UpdateOperations (logs)update test.programmersquery: { _id: "scotthernandez"}update: { $inc: { followers: 1 }}
    • 61. 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
    • 62. Thanks!• Jeff Yemin – https://twitter.com/@jeffyemin – jeff.yemin@10gen.com – https://github.com/jyemin/
    • 63. #MongoBostonThank YouJeff YeminEngineering Manager, 10gen

    ×