Morphia: SimplifyingPersistence for Java andMongoDBJeff YeminJava Evangelist, 10gen
MongoDB on the JVM• MongoDB Java Driver  – Map-based API• JVM language integrations  – Casbah (Scala)  – Jmongo (Ruby)  – ...
Morphia• Object Document Mapper  – Specified with annotations  – Implemented with reflection• Fluent query and update APIs...
Morphia by Example• Model• Test• Output
Dependencies<dependency>  <groupId>org.mongodb</groupId>  <artifactId>mongo-java-driver</artifactId>  <version>2.10.1</ver...
Repository<repository>  <id>morphia</id>  <name>Morphia</name>  <url>http://morphia.googlecode.com/svn/mavenrepo/</url>  <...
Create the DatastoreMorphia morphia = new Morphia();Mongo mongo = new Mongo();Datastore ds = morphia.createDatastore(mongo...
Entity Modelling
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.Pro...
@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.print...
@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= "Sc...
String Id (shell)> db.Programmer.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    "name" : "...
@Entity (model)@Entity("programmers")class Programmer {   @Id String githubUserName;   String name;}
@Entity (shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    "name" : "S...
More primitives (model)@Entity("programmers")class Programmer {   @Id String githubUserName;   String name;   Date memberS...
More primitives (test)Programmer scott = new Programmer();scott.userName = "scotthernandez";scott.name = "Scott Hernandez"...
More primitives (shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    "na...
Primitive Array (Model)@Entity("programmers")class Programmer {   @Id String githubUserName;   String name;   Date memberS...
Primitive Array (test)Programmer scott = new Programmer();scott.userName = "scotthernandez";scott.name = "Scott Hernandez"...
Primitive Array (shell) db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    "nam...
@Embedded (model)@Entity("programmers")class Programmer {   @Id String githubUserName;   Name name;   Date memberSince;   ...
@Embedded (test)Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = ne...
@Embedded (shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    "name" : ...
@Embedded List (model)@Entity("programmers")class Programmer {   @Id String githubUserName;   Name name;   Date memberSinc...
@Embedded (test)Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = ne...
@Embedded List (shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    …   ...
@Reference (model)@Entity("repos")class Repository {   @Id ObjectId id;   @Reference Programmer owner;   String name;   St...
@Reference (test)Programmer programmer = new Programmer();programmer.githubUserName = "scotthernandez";programmer.name = n...
@Reference (shell)> db.repos.findOne(){    "_id" : ObjectId("503297e31aa8255abe542aaa"),    "className" : "demo.Repository...
Small schema change (model)abstract class Member {  @Id String userName;  @Property("memberSince") Date since;  boolean ac...
Small schema change (test)Programmer scott = new Programmer();//…ds.save(scott);// save mongodb OrganizationOrganization m...
Small schema change (shell)> db.orgs.findOne(){    "_id" : "mongodb",    "className" : "demo.Organization",    "memberSinc...
Small schema change (shell, 2)> db.repos.find().toArray()[    {        "_id" : ObjectId("503298be1aa8b1d255e5d45b"),      ...
Querying
Find by Equality (test)•   ds.get(Programmer.class, "scotthernandez")•   ds.find(Programmer.class, "name", "Scott Hernande...
Find by Equality (logs)•   test.programmers query: { _id: "scotthernandez" }•   test.programmers query: { name: "Scott Her...
Find by Range (test)•   ds.find(Programmer.class).field("followers").greaterThan(0)•   ds.find(Programmer.class).filter("f...
Find by Range (logs)•   test.programmers query: { followers: { $gt: 0 } }•   test.programmers query: { followers: { $gt: 0...
Combining conditions (test)ds.find(Programmer.class).    field("memberSince").lessThan(dateFmt.parse("Jan 1, 2010")).     ...
Combining conditions (logs)test.programmers query: {  memberSince: { $lt: new Date(1262322000000) },  followers: { $gt: 0 }}
Find by Reference                            (test)Programmer scott = new Programmer("scotthernandez")ds.find(Repository.c...
Find by Reference (logs)test.repos query: {  owner: { $ref: "programmers", $id: "scotthernandez" }}
Indexing
@Indexed• Annotation for fields   –   value (IndexDirection)   –   name (String)   –   unique (boolean)   –   dropDups (bo...
@Indexes and @Index• @Indexes: Annotation for types  – value (Index[])• @Index  – value (String)  – Others same as @Indexe...
Updating
Updating with save (test)Programmer jeff = createJeff();ds.save(jeff);// jeff is following scott, so increment// scotts fo...
Updating with save (logs)update test.programmersquery: {  _id: "scotthernandez",}update: {  _id: "scotthernandez",  classN...
Updating with save (shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer",    ...
Optimistic Concurrency (model)@Entitypublic abstract class Member {  @Id String userName;  @Property("memberSince") Date s...
Optimistic Concurrency (logs)update test.programmersquery: {   _id: "scotthernandez",   version: 1345497713173 }update: { ...
Optimistic Concurrency(shell)> db.programmers.findOne(){    "_id" : "scotthernandez",    "className" : "demo.Programmer", ...
UpdateOperations (test)Programmer jeff = createJeff();ds.save(jeff);// increment followers of scott by oneUpdateOperations...
UpdateOperations (logs)update test.programmersquery: {  _id: "scotthernandez"}update: {  $inc: { followers: 1 }}
Web Resources• Morphia home: http://code.google.com/p/morphia/• Morphia user group:  https://groups.google.com/forum/?from...
Thanks!• Jeff Yemin   – https://twitter.com/@jeffyemin   – jeff.yemin@10gen.com   – https://github.com/jyemin/
Thank YouJeff YeminEngineering Manager, 10gen
Upcoming SlideShare
Loading in …5
×

Webinar: Simplifying Persistence for Java and MongoDB

2,198 views

Published on

Jeff Yemin will host a webinar covering the design and major features of Morphia, an Object Document Mapper (ODM) for Java and MongoDB. This webinar will start with a short introduction to MongoDB and the various options for building MongoDB applications on the JVM before taking a deep dive into Morphia. Morphia will be presented as an extended example format that demonstrates, for each feature, the domain model, a test driver, and the results as they appear in MongoDB.

Published in: Technology
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,198
On SlideShare
0
From Embeds
0
Number of Embeds
599
Actions
Shares
0
Downloads
57
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide
  • Builds on the java driver&quot;test&quot; is the name of a database&apos;
  • 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&apos;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&apos;s switch it up. Instead of embedding the repos in the programmer, let&apos;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
  • Webinar: Simplifying Persistence for Java and MongoDB

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

    ×