Spring Data Mongo: bridge MongoDB and Spring

Spring Data Mongo: bridge MongoDB and Spring

MongoDB is one of the most popular NoSQL products, Spring Data Mongo(Maven archetype id is spring-data-mongodb) tries to provides a simple approach to access MongoDB.

Configuration

Add the following code fragments in your Spring configuration.

 


 

 



 

 
    
 
  
 
  


 

 



 

 

Firstly, declare a DbFactory which is responsible for connecting to the MongoDB server.

Then, register the MongoTemplate object which envelop the data operations on MongoDB.

Lastly add mongo:repositories with an essential base-package attribute, Spring will discovery your defined Repositories in the packages.

Note: There is no transaction manager declared, Spring Data Mongo does not support Spring Transaction now.

Declare your Documents

Firstly, you have to create your domain classes. As comparison with the JPA concept, you can consider one row of records in a table is a Document in MongoDB, and a table which has many rows is a collection of Document.

@Document
public class Conference {

    @Id
    private String id;

    @Version
    private Integer version;

    @NotNull
    private String name;

    @NotNull
    private String description;

    @NotNull
    @DateTimeFormat(style = "M-")
    private Date startedDate;

    @NotNull
    @DateTimeFormat(style = "M-")
    private Date endedDate;

    @NotNull
    private String slug;

    private Address address;

    //getters and setters.
}

public class Address {

    private String addressLine1;

    private String addressLine2;

    private String zipCode;

    private String city;

    private String country

    //getters and setters
}

@Document
public class Signup {

    @Id
    private String id;

    @Version
    private Integer version;

    @DBRef
    private Conference conference;

    //other properites 
    //getters and setters
}

Conference and Signup are defined as @Document , and in Sginup, a @DBRef annotation is used to declare it is a reference of the Conference document. There is no JPA @OneToMany like annotations to define the relations between documents for MongoDB.

Address is annotated with nothing, and it is an embedded object in Conference document, in concept, it is very similar with the @Embedable class in JPA, and its lifecycle is fully controlled by its dependent Conference document.

In MongoDB, the data in the storage is presented as JSON like format.

The following is an example of Conference document.

{ 
    "_id" : ObjectId("51b422f066d41dc05f0292f0"), 
    "_class" : "com.hantsylabs.example.spring.model.Conference", 
    "version" : 0, 
    "name" : "Test JUD", 
    "description" : "JBoss User Developer Conference 2013 Boston", 
    "startedDate" : ISODate("2013-07-09T06:38:40.272Z"), 
    "endedDate" : ISODate("2013-07-16T06:38:40.272Z"), 
    "slug" : "test-jud", 
    "address" : { 
        "addressLine1" : "address line 1", 
        "addressLine2" : "address line 2", 
        "zipCode" : "510000", 
        "city" : "NY", 
        "country" : "US" 
    } 
}

The following is an example of Signup document.

{ 
    "_id" : ObjectId("51b422f066d41dc05f0292f1"), 
    "_class" : "com.hantsylabs.example.spring.model.Signup", 
    "version" : 0, 
    "firstName" : "Hantsy", 
    "lastName" : "Bai", 
    "email" : "[email protected]", 
    "phone" : "123 222 444", 
    "occupation" : "Developer", 
    "company" : "TestCompany", 
    "comment" : "test comments", 
    "createdDate" : ISODate("2013-06-09T06:38:40.288Z"), 
    "status" : "PENDING", 
    "conference" : DBRef("conference", ObjectId("51b422f066d41dc05f0292f0")) 
}

As you see, Address is embedded in the Conference document, and in Signup, there is a DBRef used to indicate it is a reference of Conference document.

@Id and @Version annotations are from the package org.springframework.data.annotation, which is similar with JPA, they are used to define the unique identification flag and version of a Document.

A String, BigInteger and Mongo specific ObjectId type property can be used as document id (annotated with the @Id annotation), Spring Data Mongo will convert it to Mongo internal id at runtime.

@Version is similar with the JPA specific @Version , Spring Data Mongo will fill this field automatically at runtime.

Spring Data Mongo also provides other annotations for the field mapping, such as @Field can be used to customize the filed name of a document in MongoDB, @Indexed is designated to create indies based on the fields at runtime.

Query

Before you do some query operations, you have to create a Repository class as the steps in before post.

@Repository
public interface ConferenceRepository extends MongoRepository

 

 
  
 
  
 {
}


 

 

MongoRepository is a Mongo specific Repository provided by Spring Data Mongo, it is dirven from PagingAndSortingRepository in Spring Data Commons.

Now you can use all the methods defined in the PagingAndSortingRepository and CrudRepository.

For example,

@Autowired
ConferenceRepository conferenceRepository;


conferenceRepository.save();
conferenceRepository.delete();
//etc

Firstly inject the ConferenceRepository in your classes, then use it as you expected.

The convention based methods are also supported by default in Spring Data Mongo, you have to research the Spring Data Mongo reference to get all available legal expression of the methods.

For example,

public Conference findBySlug(String slug);

It is used to find Conference by the slug property.

Custom Query

Like the Spring Data JPA, Spring Data Mongo also provides a @Query annotation(in the package org.springframework.data.mongodb.repository) to define and execute custom query.

For example,

@Query("{description:{ $regex: '*'+?0+'*', $options: 'i'}}")
public List

 

 
  
 
  
  searchByDescriptionLike(String like);


 

 

The value attribute of the @Query annotation can accept a Mongo aggregation expression, please refer to the official document for the Aggregation.

You can also create a Custom interface and your implementation class to execute the custom query.

The steps are similar with ones in the Spring Data JPA post.

  1. Firstly create an interface make sure the class name is ended Custom.

    public interface ConferenceRepositoryCustom {
    public List
    
       
    
       
        
     
        
      searchByDescription(String like);
    
    public void updateConferenceDescription(String description, String id );
    }
    
    
       
    
       
  2. Modify the ConferenceRepository and add ConferenceRepositoryCustom interface to be extended.

    @Repository
    public interface ConferenceRepository extends ConferenceRepositoryCustom, MongoRepository
    
       
    
       
        
     
        
     {
    }
    
    
       
    
       
  3. Create your imeplementation class to implement the methods deifned in ConferenceRepositoryCustom interface.

    public class ConferenceRepositoryImpl implements ConferenceRepositoryCustom {
    private static final Logger log = LoggerFactory
            .getLogger(ConferenceRepositoryImpl.class);
    
    @Autowired
    MongoTemplate mongoTemplate;
    
    @Override
    public List
    
       
    
       
        
     
        
      searchByDescription(String d) {
        return mongoTemplate.find(
                Query.query(Criteria.where("description").regex(
                        "[\\w]*" + d + "[\\w]*", "i")), Conference.class);
    }
    
    @Override
    public void updateConferenceDescription(String description, String id) {
        WriteResult result = mongoTemplate.updateMulti(
                Query.query(Criteria.where("id").is(id)),
                Update.update("description", description), Conference.class);
    
        log.debug("result @"+result.getField("description"));
    }
    
    }
    
    
       
    
       

Unlike the Spring Data JPA, there is no a Mongo SQL like language support in the Mongo Java Driver and Spring Data Mongo. In this implementation class, MongoTemplate is used to perform data operations.

Some other solutions I motioned before, such as DataNucleus provides standard JPA and JDO APIs for NoSQL, so using JPA APIs on Mongo is possible when use DataNucleus.

MongoTemplate

MongoTemplate simplified the document collection based operations, please refer to the Mongo official document about Collection methods.

Criteria is a fluent API to build the query condition, it try to simplify the Mongo aggregation expression.

Query is used to combine the Criteria and other query condition, such as Pageable capability.

Update is the encapsulation of the Mongo core update operation, see Mongo core operations for more details.

In fact, you can use MongoTemplate freely in the classes outside of the Repository API.

@Repository
public class AnyBean {
    @Autowired
    MongoTemplate mongoTemplate;
}

And declare context:component-scan in your configuration to discover your beans.

 


 

 

QueryDSL integration

QueryDSL supports MongoDB officially, but the Metamodel generation and data operations is dependent on a third party project named Morphia which provides JPA like APIs for Mongo operations.

But unluckily, Spring did not adopt it in Spring Data Mongo project.

  1. Extend the Spring specific QueryDslPredicateExecutor, it is from Spring Data Commons, the same interface we used in before post.

    @Repository
    public interface ConferenceRepository extends ConferenceRepositoryCustom, 
    MongoRepository
    
       
    
       
        
     
        
     ,
    QueryDslPredicateExecutor
     
        
     
        
          { } 
        
    
       
    
       
  2. Generate the Metamodels.

    Spring Data Mongo provides a custom APT processor to generate the Metamodels instead of the one provided in QueryDSL, it will scan the Spring specific @Document instead of the Morphia specific annotations.

       
    
     
        
     
        
          com.mysema.maven 
        
    
     
        
     
        
          apt-maven-plugin 
        
    
     
        
     
        
          1.0.9 
        
    
     
        
     
         
          
           
           
             process 
            
           
           
           
             target/generated-sources/java 
            
           
             org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor 
            
           
          
        
    
     
        
     
         
          
          
            com.mysema.querydsl 
           
          
            querydsl-apt 
           
          
            ${querydsl.version} 
           
          
          
          
            com.mysema.querydsl 
           
          
            querydsl-mongodb 
           
          
            apt 
           
          
            ${querydsl.version} 
           
          
         
    
    
       
    
       

    Run mvn compile to generate the Metamodels. Open the QConference class, you will find there is no difference from the early version generated for JPA entities in last post.

  3. Now you can use the APIs freely like the Spring Data JPA.

    QConference qconf = QConference.conference;
    List
    
       
    
       
        
     
        
      conferences = (List
     
        
     
        
          ) conferenceRepository .findAll(qconf.slug.eq("test-jud")); List 
         
           conferences2 = (List 
          
            ) conferenceRepository .findAll(QConference.conference.address.country.eq("CN")); 
           
          
        
    
       
    
       

    All work as expected.

    Try another one on Signup document collection.

    List
    
       
    
       
        
     
        
      signups = (List
     
        
     
        
          ) signupRepository .findAll(QSignup.signup.conference.eq(conf)); 
        
    
       
    
       

    Unfortunately, this query does not work as expected, you can find some issues have been filed about this problem on Spring JIRA. Currently, QueryDSL integration in Spring Data Mongo does not support reference(the fields marked with the @DBRef annotation) in query path. In this example, the conference caused the problem.

Spring Data Mongo also provides Geo, GridFS support abstraction which are not motioned here.

Summary

Spring Data Mongo provides simple data operations on MongoDB, due to there is no query language like JPQL for Mongo, all features provided in Spring Data Mongo based on the concept of Mongo client tools and shell interaction.

The most regrettable is it can not provide consistent experience as JPA support when adopting QueryDSL in projects.

你可能感兴趣的:(spring,mongo,spring-data)