webinar: mongodb persistence with java and morphia
DESCRIPTION
MongoDB is the leading noSQL database and as with any new technology, some of the biggest questions are about tools and integration. This webinar will cover how to use MongoDB from a Java application and introduce Morphia, the object document mapping library. It will cover the essential features of the framework with examples before moving on to some of the more advanced and upcoming features such as text search and aggregation framework support.TRANSCRIPT
MongoDB Persistence with Java and Morphia
Software Engineer, MongoDB
Justin Lee
AgendaIntroduction
Getting Started
Modeling
Querying
Updating
Indexing
Road Map
What is Morphia?• Object document mapper — https://github.com/mongodb/morphia
• Provides mapping to/from Java objects to mongodb
• Annotation-based
• Embedded objects/documents
• References (lazy or eager)
• Fluent query/update APIs
• Runtime validation
Why Morphia?• Offload object marshaling
• automatically keeps up as objects evolve: new, removed, renamed
• Higher abstraction
• Simplified management of indexes
• Unify code with schema management
• Object/Document Versioning
A Brief History
• Created by Scott Hernandez
• Hired by 10Gen —> started working on the kernel
• Morphia left alone for a couple of years
• Lots of uncertainty
• James Green forked morphia
• I was hired in June, 2013 in part to pick up Morphia
• 5 releases since with another pending
Getting Started
Adding morphia — Maven
<dependency>
<groupId>org.mongodb.morphia</groupId>
<artifactId>morphia</artifactId>
<version>0.105</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.11.3</version>
</dependency>
Adding morphia — Gradle
compile "org.mongodb.morphia:morphia:0.105"
compile "org.mongodb:mongo-java-driver:2.11.3"
!
!
Initializing morphia
Morphia morphia = new Morphia();
Datastore datastore = morphia.createDatastore(
new MongoClient(), “morphia-demo");
morphia.mapPackage("org.mongodb.morphia.demo");
datastore.ensureIndexes();
!
Entity Modeling
Basic Entity
@Entity
public class GithubUser {
private String userName;
private String fullName;
!
private Date memberSince;
}
Basic Entity
@Entity
public class GithubUser {
private String userName;
private String fullName;
!
private Date memberSince;
}
(value = “users")
Basic Entity
@Entity
public class GithubUser {
private String userName;
private String fullName;
!
private Date memberSince;
}
(value = "users", noClassnameStored = true)
Basic Entity
@Entity
public class GithubUser {
private String userName;
private String fullName;
!
private Date memberSince;
}
(value = "users", noClassnameStored = true)
@Id
Basic Entity
@Entity
public class GithubUser {
private String userName;
private String fullName;
!
private Date memberSince;
}
(value = "users", noClassnameStored = true)
@Id
@Property("since")
Basic Entity — Saving
GithubUser user = new GithubUser("evanchooly");
user.fullName = "Justin Lee";
user.memberSince = sdf.parse("6-15-1987");
datastore.save(user);
Basic Entity — Shell
repl0:PRIMARY> db.users.findOne() { "_id" : "evanchooly", "fullName" : "Justin Lee", "since" : ISODate("1987-06-15T04:00:00Z") }
Complex Entities
@Entity("orgs") public class Organization { @Id public String name; ! public Organization(final String name) { this.name = name; } }
Complex Entities
@Embedded public class Settings { public String defaultBranch = "master"; public Boolean allowWiki = false; public Boolean allowIssues = true; }
Complex Entities
@Entity("repos") public class Repository { @Id public String name; @Reference public Organization organization; @Reference public GithubUser owner; public Settings settings = new Settings(); }
Complex Entities
@Entity(value = "users", noClassnameStored = true) public class GithubUser { @Id public final String userName; public String fullName; @Property("since") public Date memberSince; @Reference(lazy = true) public List<Repository> repositories = new ArrayList<>(); }
Complex Entities
Organization org = new Organization("mongodb"); !GithubUser user = new GithubUser("evanchooly"); user.fullName = "Justin Lee"; user.memberSince = sdf.parse("6-15-1987"); !datastore.save(org); datastore.save(user); !datastore.save(new Repository(org, "morphia")); datastore.save(new Repository(user, "morphia"));
Complex Entities — Shell
repl0:PRIMARY> show collections orgs repos system.indexes users
Complex Entities — Shell
repl0:PRIMARY> db.orgs.findOne(); { "_id" : "mongodb", "className" : "org.mongodb.morphia.demo.Organization" }
Complex Entities — Shellrepl0:PRIMARY> db.repos.find().pretty(); { "_id" : "mongodb/morphia", "className" : "org.mongodb.morphia.demo.Repository", "organization" : DBRef("orgs", "mongodb"), "settings" : { "defaultBranch" : "master", "allowWiki" : false, "allowIssues" : true } } { "_id" : "evanchooly/morphia", "className" : "org.mongodb.morphia.demo.Repository", "owner" : DBRef("users", "evanchooly"), "settings" : { … } }
Complex Entities — Shell
repl0:PRIMARY> db.users.findOne(); { "_id" : "evanchooly", "fullName" : "Justin Lee", "since" : ISODate("1987-06-15T04:00:00Z"), "repositories" : [ DBRef("repos", "mongodb/morphia"), DBRef("repos", "evanchooly/morphia") ] }
Queries
Basic Query
Query<Repository> query = datastore.createQuery(Repository.class); Repository repository = query.get(); !runQuery called morphia-demo.repos {} !List<Repository> repositories = query.asList(); !runQuery called morphia-demo.repos {} !Iterable<Repository> fetch = query.fetch(); !… ?
Basic Query
Query<Repository> query = datastore.createQuery(Repository.class); query.field("owner").equal(evanchooly).get(); !runQuery called morphia-demo.repos { owner: { $ref: "users", $id: "evanchooly" } }
Complex Entities
@Entity("repos") public class Repository { @Id public String name; @Reference public Organization organization; @Reference public GithubUser owner; public Settings settings = new Settings(); }
Basic Query — @Property
@Entity(value = "users", noClassnameStored = true)
public class GithubUser {
@Id
private String userName;
private String fullName;
@Property("since")
private Date memberSince;
}
Basic Query — @Property
datastore.createQuery(GithubUser.class) .field("memberSince").equal(date).get(); !GithubUser{userName='evanchooly', fullName='Justin Lee', memberSince=Mon Jun 15 00:00:00 EDT 1987} !datastore.createQuery(GithubUser.class) .field("since").equal(date).get(); !GithubUser{userName='evanchooly', fullName='Justin Lee', memberSince=Mon Jun 15 00:00:00 EDT 1987}
Updates
Updating Entities
evanchooly.followers = 12; datastore.save(evanchooly);
Multiple Updates
UpdateOperations<GithubUser> update = datastore.createUpdateOperations( GithubUser.class) .inc("followers").set("following", 42); Query<GithubUser> query = datastore.createQuery(GithubUser.class) .field(“followers”) .equal(0); datastore.update(query, update); !update morphia-demo.users query: { followers: 0 } update: { $set: { following: 42 }, $inc: { followers: 1 } }
Versioned Updates
@Entity("orgs") public class Organization { @Id public String name; @Indexed public Date created; @Version(“v”) private long version; !… !}
Versioned Updates
Organization organization = datastore.createQuery(Organization.class).get(); Organization organization2 = datastore.createQuery(Organization.class).get(); !datastore.save(organization); // fine datastore.save(organization); // fine datastore.save(organization2); !java.util.ConcurrentModificationException: Entity of class org.mongodb.morphia.demo.Organization (id='mongodb',version='1') was concurrently updated.
Indexes
Indexes — Fields
@Entity("orgs") public class Organization { @Id public String name; @Indexed(value = IndexDirection.ASC, unique = false, name = "", dropDups = false, background = false, sparse = false, expireAfterSeconds = -1) public Date created; !… }
Indexes — Fields
repl0:PRIMARY> db.orgs.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "morphia-demo.orgs" }, { "v" : 1, "key" : { "created" : 1 }, "name" : "created_1", "ns" : "morphia-demo.orgs" } ]
Indexes — Classes
@Entity(value = "users", noClassnameStored = true) @Indexes({ @Index(value ="userName, -followers", name = "popular") }) public class GithubUser { @Id public String userName; public String fullName; @Property("since") public Date memberSince; public Date lastActive; @Reference(lazy = true) public List<Repository> repositories = new ArrayList<>(); public int followers = 0; public int following = 0; !…
What’s Next
The Road to 1.0
• It’s short
• Aggregation support
• Text Searching
• Improved geo support
• Handful of bug fixes
Resources
• Morphia Homepage https://github.com/mongodb/morphia
• Discussions Forum https://groups.google.com/forum/#!forum/morphia
• This presentation and code https://github.com/evanchooly/morphia-demo
Questions?
MongoDB Persistence with Java and Morphia
Software Engineer, MongoDB
Justin Lee