1. 程式人生 > >MongoDB--Spring Data MongoDB詳細的操作手冊(增刪改查)

MongoDB--Spring Data MongoDB詳細的操作手冊(增刪改查)

  在NoSQL盛行的時代,App很大可能會涉及到MongoDB資料庫的使用,而也必須學會在Spring boot使用Spring Data連線MongoDB進行資料增刪改查操作,如下為詳細的操作手冊。

1. 依賴

直接匯入spring-data-mongodb包或者使用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 框架使用最新的 -->
<spring.framework.version>5.2.0.RELEASE</spring.framework.version>

<!--用一即可-->
<!--使用Spring Boot starter-->
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2. 屬性檔案application.properties

#mongodb連線地址,叢集用“;”隔開
spring.mongo.mongoDatabaseAddress=10.110.112.165:27092;10.110.112.166:27092
#mongo資料名
spring.mongo.dbname=mongodb
#mongo使用者
spring.mongo.username=mongodbopr
#mongo密碼
spring.mongo.password=123456
#mongo最大連線數
spring.mongo.connectionsPerHost=50

3. mongodb 配置

註冊Mongo例項配置:

@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;
    
    /**
     * 獲取mongodb的地址
     *
     * @return
     */
    private List<ServerAddress> getMongoDbAddress() {
        List<ServerAddress> serverAddrList = new ArrayList<ServerAddress>();
        //如果有多個伺服器的話
        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;
    }
    /**
     * 設定連線引數
     */
    private MongoClientOptions getMongoClientOptions() {
        MongoClientOptions.Builder builder = MongoClientOptions.builder();
        // todo 新增其他引數配置
        //最大連線數
        builder.connectionsPerHost(Integer.valueOf(connectionsPerHost));
        MongoClientOptions options = builder.readPreference(ReadPreference.nearest()).build();
        return options;
    }
    /**
     *
     * @return
     */
    @Bean
    public MongoClient mongoClient() {
        //使用資料庫名、使用者名稱密碼登入
        MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray());
        //建立Mongo客戶端
        return new MongoClient(getMongoDbAddress(), credential, getMongoClientOptions());
    }
    /**
     * 註冊mongodb操作類
     * @param mongoClient
     * @return
     */
    @Bean
    @ConditionalOnClass(MongoClient.class)
    public MongoTemplate mongoTemplate(MongoClient mongoClient) {
        MongoTemplate mongoTemplate = new MongoTemplate(new SimpleMongoDbFactory(mongoClient, dbname));
        return mongoTemplate;
    }
}

4. mongodb操作

使用MongoTemplate類進行增刪改查

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

    /**
     * 新增文件
     *
     * @param userDTO
     * @return
     */
    public UserDTO insert(UserDTO userDTO) {
        //insert方法並不提供級聯類的儲存,所以級聯類需要先自己先儲存
        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);
    }

    /**
     * 刪除文件
     * NOTE:remove方法不支援級聯刪除所以要單獨刪除子資料
     * @param name
     */
    public void remove(String name) {
        //根據名字查詢資料並刪除
        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)), UserDTO.class);
        //remove方法不支援級聯刪除所以要單獨刪除子資料
        List<AddressDTO> addressList = userDTO.getAddressList();
        for (AddressDTO addressDTO : addressList) {
            mongoTemplate.remove(addressDTO);
        }
        //刪除主資料
        mongoTemplate.remove(userDTO);
    }

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

    /**
     * 查詢文件
     * @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);
        //基於sort排序使用findOne查詢最新一條記錄
        UserDTO userDTO = mongoTemplate.findOne(Query.query(Criteria.where("name").is(name)).with(sort), UserDTO.class);
        //模糊查詢
        List<UserDTO> userDTOList = mongoTemplate.find(Query.query(Criteria.where("name").is(name).regex(name)).with(sort), UserDTO.class);
        //分頁查詢
        Pageable pageable = PageRequest.of(3, 20, sort);
        List<UserDTO> userDTOPageableList = mongoTemplate.find(Query.query(Criteria.where("name").is(name)).with(pageable), UserDTO.class);
        //總數
        long conut = mongoTemplate.count(Query.query(Criteria.where("name").is(name)), UserDTO.class);
        Page<UserDTO> page = new PageImpl(userDTOPageableList, pageable, conut);
    }
}

NOTE:
  在開發中,如果從任何MongoDB操作返回的com.mongodb.WriteResult包含錯誤,則可以方便地記錄或引發異常。 通常,在開發過程中很容易忘記執行此操作,然後最終得到一個看似執行成功的App,但實際上該資料庫操作發生異常,沒執行成功。 可以將MongoTemplateWriteResultChecking屬性設定為以下值之一:

  • EXCEPTION:引發Exception
  • NONE:不執行任何操作,預設值

  對於更高階的情況,可以將每個操作設定不同的WriteConcern值(用於刪除,更新,插入和儲存操作),則可以在MongoTemplate上配置WriteConcernResolver的策略介面。 由於MongoTemplate用於持久化POJO,因此WriteConcernResolver允許您建立一個策略,該策略可以將特定的POJO類對映到WriteConcern值。

WriteConcernResolver介面:

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

自定義WriteConcernResolver介面,實現不同WriteConcern策略:

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. 常用的類以及方法解析

5.1 MongoClient、ServerAddress、MongoCredential以及MongoClientOptions

  基於ServerAddress單機或者Replica Set在使用MongoClient連線mongodb資料庫註冊mongo例項,在註冊示例中可能要使得MongoCredential賬號密碼驗證以及使用MongoClientOptions配置mongodb其他的引數。

MongoClient常用的構造器方法:

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結合SortCriteriaQueryUpdate以及分頁Pageable類靈活地進行對mongodb資料庫進行增刪改查。

query方法:

//根據查詢條件查詢
 public <T> List<T> find(Query query, Class<T> entityClass){}
 //根據查詢條件查詢返回一條記錄
 public <T> <T>findOne(Query query, Class<T> entityClass){}
 //查詢該collection所有記錄
 public <T> List<T> findAll(Class<T> entityClass){}

insert方法:

//新增一條記錄
 public <T> T insert(T objectToSave){}
 //在collectionName中新增一條記錄
 public <T> T insert(T objectToSave, String collectionName) {}
 //
 public <T> T save(T objectToSave){}

remove方法:

//根據Object刪除
 public DeleteResult remove(Object object) {}
 //根據查詢條件進行刪除
 public DeleteResult remove(Query query, Class<?> entityClass){}

update方法:

 //
 public UpdateResult upsert(Query query, Update update, Class<?> entityClass) {}
 //更新查詢出來的第一條記錄
 public UpdateResult updateFirst(Query query, Update update, String collectionName) {}

5.3 Sort

Sort查詢排序類。Sort類常用方法:

//構造方法建立一個排序。direction為排序方向的列舉型別,properties為排序欄位陣列
Sort(Sort.Direction direction, String... properties)
//多個排序條件連結
and(Sort sort)
//返回升序排列物件
ascending()	
//返回降序排列物件
descending()	

5.4 Criteria

Criteria查詢條件類,類似於SQL的where,常用方法:

//宣告定義查詢條件,且為靜態方法
where(String key)
//與操作
and(String key)
//正則表示式,即可為模糊查詢
regex(String re)
//包含
in(Object... o)	
//大於
gt(Object o)
//大於等於
gte(Object o)
//等於
is(Object o)
//小於
lt(Object o)
//小於等於
lte(Object o) 
//非
not()
//建立與操作
andOperator(Criteria... criteria)	

5.5 Query

Query查詢物件,具有查詢的全部資訊,其中包括篩選條件、排序、返回數量等。常用的方法:

//定義查詢物件,靜態方法
query(CriteriaDefinition criteriaDefinition)
//在本次查詢新增一個CriteriaDefinition查詢條件
addCriteria(CriteriaDefinition criteriaDefinition)
//新增一個Sort排序物件
with(Sort sort)
//新增一個Pageable分頁物件、通常情況下,分頁和排序一起使用。
with(Pageable pageable)

詳細介面資訊可檢視【MogoDB API官方文件】

6.常用註解

註解 解析
@Id 用於標記id欄位,沒有標記此欄位的實體也會自動生成id欄位,但是我們無法通過實體來獲取id。id建議使用ObjectId型別來建立
@Document 用於標記此實體類是mongodb集合對映類
@DBRef 用於指定與其他集合的級聯關係,但是需要注意的是並不會自動建立級聯集合
@Indexed 用於標記為某一欄位建立索引
@CompoundIndex 用於建立複合索引
@TextIndexed: 用於標記為某一欄位建立全文索引
@Language 指定documen語言
@Transient: 被該註解標註的,將不會被錄入到資料庫中。只作為普通的javaBean屬性
@Field: 用於指定某一個欄位對映到資料庫中的名稱