MongoDB - Spring Data MongoDB Detailed Manual (Add, Delete and Revise)

Keywords: Mobile Spring MongoDB Database less

_In the era of NoSQL, App is likely to involve the use of MongoDB database, but also must learn to use Spring Data to connect MongoDB in Spring boot for data addition, deletion and modification operations, as follows: detailed operation manual.

1. Dependence

Import spring-data-mongodb packages directly or use Spring Boot starter

<dependencies>
  <!-- other dependency elements omitted -->
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>2.2.0.RELEASE</version>
  </dependency>
</dependencies>
<!--spring Framework uses the latest -->
<spring.framework.version>5.2.0.RELEASE</spring.framework.version>

<!--Just use one.-->
<!--Use Spring Boot starter-->
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2. Property file application.properties

#mongodb Connection Address, Cluster Separated by ";"
spring.mongo.mongoDatabaseAddress=10.110.112.165:27092;10.110.112.166:27092
#mongo data name
spring.mongo.dbname=mongodb
#mongo users
spring.mongo.username=mongodbopr
#mongo password
spring.mongo.password=123456
#Maximum number of mongo connections
spring.mongo.connectionsPerHost=50

3. mongodb configuration

Register Mongo instance configuration:

@Configuration
public class MongodbConfig {
    public static final String COMMA = ";";
    public static final String COLON = ":";
    
    @Value("${spring.mongo.mongoDatabaseAddress}")
    private String mongoDatabaseAddress;
    
    @Value("${spring.mongo.username}")
    private String username;
    @Value("${spring.mongo.dbname}")
    private String dbname;
    
    @Value("${spring.mongo.password}")
    private String password;
    
    @Value("${spring.mongo.connectionsPerHost}")
    private String connectionsPerHost;
    
    /**
     * Get the address of mongodb
     *
     * @return
     */
    private List<ServerAddress> getMongoDbAddress() {
        List<ServerAddress> serverAddrList = new ArrayList<ServerAddress>();
        //If there are multiple servers
        if (this.mongoDatabaseAddress.indexOf(COMMA) > 0) {
            String[] addressArrays = mongoDatabaseAddress.split(COMMA);
            String[] hostPort;
            for (String address : addressArrays) {
                hostPort = address.split(COLON);
                ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));
                serverAddrList.add(serverAdress);
            }
        } else {
            String[] hostPort = mongoDatabaseAddress.split(COLON);
            ServerAddress serverAdress = new ServerAddress(hostPort[0], Integer.valueOf(hostPort[1]));
            serverAddrList.add(serverAdress);
        }
        return serverAddrList;
    }
    /**
     * Setting connection parameters
     */
    private MongoClientOptions getMongoClientOptions() {
        MongoClientOptions.Builder builder = MongoClientOptions.builder();
        // Adding additional parameter configurations to todo
        //maximum connection
        builder.connectionsPerHost(Integer.valueOf(connectionsPerHost));
        MongoClientOptions options = builder.readPreference(ReadPreference.nearest()).build();
        return options;
    }
    /**
     *
     * @return
     */
    @Bean
    public MongoClient mongoClient() {
        //Log in using database name and user name password
        MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray());
        //Creating Mongo Client
        return new MongoClient(getMongoDbAddress(), credential, getMongoClientOptions());
    }
    /**
     * Register the mongodb operation class
     * @param mongoClient
     * @return
     */
    @Bean
    @ConditionalOnClass(MongoClient.class)
    public MongoTemplate mongoTemplate(MongoClient mongoClient) {
        MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoDbFactory(mongoClient, dbname));
        return mongoTemplate;
    }
}

4. mongodb operation

Use the MongoTemplate class for add-delete checks

@Service
public class MongodbService {
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * New Documents
     *
     * @param userDTO
     * @return
     */
    public UserDTO insert(UserDTO userDTO) {
        //The insert method does not provide the storage of cascade classes, so the cascade classes need to be saved first by themselves.
        return mongoTemplate.insert(userDTO);
    }

    public UserDTO save(UserDTO userDTO) {
        Sort sort = new Sort(Sort.Direction.DESC, "name");
        userDTO = mongoTemplate.findOne(Query.query(Criteria.where("")).with(sort), UserDTO.class);
        return mongoTemplate.save(userDTO);
    }

    /**
     * remove document
     * NOTE:remove Method does not support cascading deletion, so delete subdata separately
     * @param name
     */
    public void remove(String name) {
        //Query the data by name and delete it
        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)), UserDTO.class);
        //The remove method does not support cascading deletion, so delete subdata separately
        List<AddressDTO> addressList = userDTO.getAddressList();
        for (AddressDTO addressDTO : addressList) {
            mongoTemplate.remove(addressDTO);
        }
        //Delete master data
        mongoTemplate.remove(userDTO);
    }

    /**
     * Update Documents
     * @param userDTO
     */
    public void update(UserDTO userDTO) {
        mongoTemplate.updateFirst(Query.query(Criteria.where("name").is(userDTO.getName())), Update.update("age", userDTO.getAge()), UserDTO.class);
    }

    /**
     * consult your documentation
     * @param name
     */
    public void find(String name) {
        Sort sort = new Sort(Sort.Direction.DESC, "name");
        List<UserDTO> userDTOS = mongoTemplate.find(Query.query(Criteria.where("name").is(name)), UserDTO.class);
        //Use findOne to query the latest record based on sort sort sort
        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)).with(sort), UserDTO.class);
        //Fuzzy Query
        List<UserDTO> userDTOList = mongoTemplate.find(Query.query(Criteria.where("name").is(name).regex(name)).with(sort), UserDTO.class);
        //Paging query
        Pageable pageable = PageRequest.of(3, 20, sort);
        List<UserDTO> userDTOPageableList = mongoTemplate.find(Query.query(Criteria.where("name").is(name)).with(pageable), UserDTO.class);
        //Total
        long conut = mongoTemplate.count(Query.query(Criteria.where("name").is(name)), UserDTO.class);
        Page<UserDTO> page = new PageImpl(userDTOPageableList, pageable, conut);
    }
}

NOTE:
In development, if com.mongodb.WriteResult returned from any MongoDB operation contains errors, it is easy to record or throw exceptions. Usually, it's easy to forget to do this during the development process and eventually get an App that looks like it's running successfully, but in fact, the database operation is abnormal and failed. The WriteResultChecking property of MongoTemplate can be set to one of the following values:

  • EXCEPTION: Initiating Exception
  • NONE: No operation, default

For more advanced cases, you can set different WriteConcern values for each operation (for deletion, update, insert and save operations), and you can configure WriteConcernResolver's policy interface on MongoTemplate. Because MongoTemplate is used to persist POJOs, WriteConcernResolver allows you to create a policy that maps specific POJO classes to WriteConcern values.

WriteConcernResolver interface:

public interface WriteConcernResolver {
  WriteConcern resolve(MongoAction action);
}

Customize WriteConcernResolver interface to implement different WriteConcern policies:

private class MyAppWriteConcernResolver implements WriteConcernResolver {

  public WriteConcern resolve(MongoAction action) {
    if (action.getEntityClass().getSimpleName().contains("UserDTO")) {
      return WriteConcern.NONE;
    } else if (action.getEntityClass().getSimpleName().contains("Metadata")) {
      return WriteConcern.JOURNAL_SAFE;
    }
    return action.getDefaultWriteConcern();
  }
}

5. Common Classes and Method Resolution

5.1 MongoClient, Server Address, MongoCredential and MongoClient Options

_Based on Server Address stand-alone or Replica Set, mongo instances are registered using MongoClient to connect to mongodb database. In the registration example, it is possible to make the password verification of mongo Credential account and configure other parameters of mongodb using MongoClient Options.

The constructor methods commonly used by MongoClient are:

public MongoClient(String host){}
public MongoClient(MongoClientURI uri){}
public MongoClient(String host, MongoClientOptions options) {}
public MongoClient(ServerAddress addr, MongoCredential credential, MongoClientOptions options){}
public MongoClient(List<ServerAddress> seeds, MongoCredential credential, MongoClientOptions options){}

5.2 MongoTemplate

MongoTemplate is used in combination with Sort, Criteria, Query, Update and Pageable classes to flexibly add, delete and modify mongodb database.

query method:

//Query according to query condition
 public <T> List<T> find(Query query, Class<T> entityClass){}
 //Returns a record based on the query condition
 public <T> <T>findOne(Query query, Class<T> entityClass){}
 //Query all records of the collection
 public <T> List<T> findAll(Class<T> entityClass){}

insert method:

//Add a new record
 public <T> T insert(T objectToSave){}
 //Add a new record in collectionName
 public <T> T insert(T objectToSave, String collectionName) {}
 //
 public <T> T save(T objectToSave){}

remove method:

//Delete according to Object
 public DeleteResult remove(Object object) {}
 //Delete according to query condition
 public DeleteResult remove(Query query, Class<?> entityClass){}

update method:

 //
 public UpdateResult upsert(Query query, Update update, Class<?> entityClass) {}
 //Update the first record of the query
 public UpdateResult updateFirst(Query query, Update update, String collectionName) {}

5.3 Sort

Sort query sort class. Common methods of the Sort class:

//The constructor creates a sort. Direction is an enumeration type of sort direction, and properties are an array of sort fields
Sort(Sort.Direction direction, String... properties)
//Multiple Sort Conditional Links
and(Sort sort)
//Returns an ascending array object
ascending()	
//Returns the descending array object
descending()	

5.4 Criteria

Criteria query condition class, similar to where in SQL, is commonly used:

//Declare that the query condition is defined, and that it is a static method
where(String key)
//And operation
and(String key)
//Regular expression can be used as fuzzy query
regex(String re)
//Contain
in(Object... o)	
//greater than
gt(Object o)
//Greater than or equal to
gte(Object o)
//Be equal to
is(Object o)
//less than
lt(Object o)
//Less than or equal to
lte(Object o) 
//wrong
not()
//Creation and operation
andOperator(Criteria... criteria)	

5.5 Query

Query query object, which has all the information of query, including filter conditions, sorting, number of returns, etc. Common methods:

//Define query objects, static methods
query(CriteriaDefinition criteriaDefinition)
//Add a Criteria Definition query condition to this query
addCriteria(CriteriaDefinition criteriaDefinition)
//Add a Sort sort object
with(Sort sort)
//Add a Pageable paging object, usually used with sorting.
with(Pageable pageable)

Detailed interface information can be viewed [Official Documentation of MogoDB API]

6. Common Notes

annotation analysis
@Id An entity that does not tag an id field will automatically generate an id field, but we cannot get an id through an entity. id suggests using ObjectId type to create
@Document Used to mark this entity class as a mongodb set mapping class
@DBRef Used to specify cascading relationships with other collections, but it is important to note that cascading collections are not automatically created
@Indexed Used to mark up an index for a field
@CompoundIndex Used to create composite indexes
@TextIndexed: Used to mark a field to create a full-text index
@Language Specify documen t language
@Transient: Those annotated by this annotation will not be entered into the database. Just as a normal javaBean attribute
@Field: Used to specify the name of a field mapped to a database

Posted by keegan on Tue, 08 Oct 2019 17:45:58 -0700