Wednesday, April 28, 2010

MongoDB with Sculptor - Repository

This post is part of a series of articles describing the support for MongoDB in Sculptor. This post explains how Repositories with useful operations are defined and how queries can be expressed in terms of the domain.

In the visualization of the blog sample you maybe noticed that there are Services with findById, findAll, save and delete even though they were not explicitly defined in the model. They come from that the domain objects are marked with with scaffold. That automatically generates some predefined CRUD operations in the Repository and corresponding Service.


Entity BlogPost {
scaffold
- Blog inBlog
String slug key
String title
String body
DateTime published nullable
Set<String> tags
- Author writtenBy
- List<Comment> comments opposite forPost
}


You can also define the needed operations explicitly like this:


Entity BlogPost {
- Blog inBlog
String slug key
String title
String body
DateTime published nullable
Set<String> tags
- Author writtenBy
- List<Comment> comments opposite forPost

Repository BlogPostRepository {
save;
delete;
findAll(PagingParameter pagingParameter);
findById;
findByKey;
List<@BlogPost> findPostsInBlog(@Blog blog);
List<@BlogPost> findPostsWithComments => AccessObject;
List<@BlogPost> findPostsWithTags(Set<String> tags);
protected findByCondition;
}


You don't need to do any manual coding for the built in operations, such as save, delete, findAll, findById, findByKey.
findByKey is for the natural key, i.e. the attributes marked with key (slug above).

There is good support for pagination and sorting.

As you see in the above sample it is also possible to define your own repository operations, such as findPostsWithTags.

findByCondition

The most interesting finder is findByCondition. Queries can expressed with an internal DSL that support code completion and refactoring. It is best illustrated with a few samples.


public List<BlogPost> findPostsInBlog(Blog blog) {
List<ConditionalCriteria> condition = criteriaFor(BlogPost.class)
.withProperty(inBlog()).eq(blog)
.orderBy(published()).descending()
.build();
return findByCondition(condition);
}



public List<BlogPost> findPostsWithGreatComments() {
List<ConditionalCriteria> condition = criteriaFor(BlogPost.class)
.withProperty(comments().title()).ignoreCaseLike(".*great.*")
.and().withProperty(published()).isNotNull()
.orderBy(published()).descending().build();
return findByCondition(condition);
}


The ConditionalCriteriaBuilder has support for defining queries with eq, like, between, lessThan, greaterThan, in, and, not, orderBy, and some more.

You can of course also work directly with the underlaying MongoDB DBCollection and DBObject for doing advanced queries that might not be supported by findByCondition.

No comments:

Post a Comment