Spring Boot 整合——MongoDB整合2(MongoDB實體建立以及簡單CRUD)
文章前面
關於版本
依賴 | 版本 |
---|---|
springboot | 2.0.8.RELEASE |
mongodb | 4.0.14 |
本內容只是為了介紹mongodb最基礎的使用以及配置,作為一個知名的資料庫,其存在相當多的高階用法,展開來介紹內容會相當多,當然本人並非相關領域的大神,下面內容只不過整理了自己日常使用的一些積累。是對自己經驗的積累,也希望能幫助後來的同學
關於專案
本內容也是我嘗試整理工作中接觸過各種工具在springboot中使用的方法。下面介紹的所有方法都已經提供了測試用例。因為每個例子涉及程式碼較多,所以文章中只貼出了部分程式碼。全部的程式碼在這裡:https://gitee.com/daifyutils/springboot-samples。
MongoDB表(集合)的定義
在MySQL中儲存一類資料的集合體被叫做表(table),而在mongodb中被叫做集合(collections)。而mongodb中每一條資料被稱為文件(document)。
於傳統的MySQL需要提前在資料庫中完成表建立不同,使用Spring Boot操作mongodb的時候不需要再資料庫中建立集合結構,而通過將實體定義為mongodb實體來完成集合的建立。
定義實體需要的註解
Spring Data為了定義mongodb的集合結構,提供了下面幾個註解
註解 | 說明 |
---|---|
@Document | 標識當前實體是一個mongodb實體 |
@Id | 標識當前欄位為主鍵,需要注意的是此註解只能存在一個 |
@Indexed | 標識當前欄位需要新增索引,新增索引後的欄位,在進行查詢操作的時候會提高速度 |
@CompoundIndex | 標識一個聯合索引 |
@Field | 對當前欄位的額外內容進行定義,主要是用來定義集合中欄位實際名稱 |
@Transient | 標識此欄位為java屬性而非mongodb欄位 |
@DBRef | 將此欄位同另外一個mongodb的文件進行關聯 |
註解的使用
註解的使用
現在建立下面兩個實體
import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.index.CompoundIndexes; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import java.util.List; @Data @Document(collection = "Province") @CompoundIndexes({ @CompoundIndex(name = "userName_age_idx",def = "{'provinceName': 1,'provinceCode': -1}") }) public class Province { @Id private String id; private String provinceName; private String provinceCode; @DBRef private List<City> cities; }
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
@Data
@Document(collection = "City")
public class City {
@Id
private String id;
private String cityName;
@Indexed
@Field(value = "code")
private String cityCode;
@Transient
private String cityRemark;
}
關於上面的例子中使用的註解作用:
@Document
上面例子中使用了@Document定義了兩個資料集合Province
和City
。
@Id
資料集合Province
和City
中id欄位被定義為主鍵。
@Indexed
資料集合City
中將cityCode欄位添加了索引。
@Field(value = “code”)
在定義mongodb欄位的時候,不新增@Field
的註解時儲存到集合中的欄位名和實體中的屬性名保持一致,而資料集合City
中cityCode欄位添加了上面註解後實際儲存到集合中的欄位會被設定為code
@Transient
此欄位標識的cityRemark
只是作為java屬性來使用,在將資料儲存至mongodb的時候此內容並不會儲存下來。
@DBRef
將此欄位和另外一個mongodb文件進行關聯,新增此註解和不新增此註解的主要區別在於。當不新增此註解的時候,此欄位中的City
內容會作為Province
文件的一部分儲存起來,而當新增此註解後Province
文件中只會維持City
的主鍵值。
當我們建立一些Province
和City
資料後可以看到Province
中資料內容如下:
@CompoundIndex
將provinceName
和provinceCode
欄位作為一個聯合索引。數字引數指定索引的方向,1為正序,-1為倒序。這裡需要注意在使用@Indexed
標識索引的時候,建立集合後會自動建立對應的索引,而使用@CompoundIndex
標識索引的時候是在新增資料之後關聯索引才產生。
mongodb簡單的CRUD
通過Spring Data操作mongodb主要是使用兩種資料操作工具,一種是MongoTemplate
他是mongodb資料訪問模板提供了基礎的資料訪問介面。而另外一種是建立一種繼承MongoRepository
的資料訪問介面,MongoRepository
是基於JPA規則的資料訪問介面,它提供了基礎的CRUD操作,雖然無法實現一些複雜的統計以及聯表查詢,但是因為提供了自定義方法
使其對單表的操作上會非常簡單。
基於MongoRepository的CRUD
儲存&更新
MongoRepository的儲存和更新都是使用save方法,而對於批量處理MongoRepository提供了saveAll方法
@Override
public void saveOne(Product product) {
productRepository.save(product);
}
@Override
public void batchSave(List<Product> products) {
productRepository.saveAll(products);
}
刪除
MongoRepository
關於刪除提供的是delete(實體物件)
的方法,此方法需要將mongodb實體作為引數傳遞進來,很多時候我們的刪除都是基於ID
的,所以deleteById
使用的頻率會比較多一些。但是基於ID的刪除MongoRepository
並沒有提供批量處理的方法,但是可以使用自定義方法
建立一個deleteAllByIdIn方法來實現批量刪除
@Override
public void deleteOne(String id) {
productRepository.deleteById(id);
}
@Override
public void batchDelete(List<String> idList) {
productRepository.deleteAllByIdIn(idList);
}
查詢
MongoRepository
關於查詢需要配合Example使用,此類會將mongodb實體中的內容轉換為查詢的條件來進行篩選,而對於需要進行分頁或排序操作的查詢,需要配合Pageable和Sort的使用來實現資料分頁。
@Override
public List<Product> queryByEntity(Product product) {
Example<Product> of = Example.of(product);
List<Product> all = productRepository.findAll(of);
return all;
}
@Override
public Page<Product> pageByEntity(Product product,int page,int size) {
Example<Product> of = Example.of(product);
Pageable pageable = PageRequest.of(page - 1,size);
Page<Product> all = productRepository.findAll(of,pageable);
return all;
}
需要注意,有些時候我們建立自定義方法
後需要進行分頁查詢,此時關於分頁的內容並不需要在方法名稱上做任何改動,只需要在最後新增入參Pageable,並將返回內容修改為Page<{mongodb資料實體}>此方法就可以使用分頁引數並返回分頁資料了。
基於MongoTemplate的CRUD
儲存
MongoTemplate雖然很多查詢條件需要使用者自行設定,但是其也提供了基礎的查詢介面。比如MongoTemplate提供了save方法來儲存資料。
@Override
public void saveOneByTemplate(Product product) {
mongoTemplate.save(product);
}
更新
MongoTemplate針對資料更新提供了upsert
、updateFirst
、updateMulti
等方法上面幾種方法都是基於doUpdate
的實現的。這裡就需要使用者提供一個定位更新資料的Query
。
/**
* 執行插入。
* @param queryProduct
* @param product
*/
@Override
public void updateOneByTemplate(Product queryProduct,Product product) {
Query query = new Query();
Criteria criteria = Criteria.byExample(Example.of(queryProduct));
query.addCriteria(criteria);
Update update = new Update();
update.set("id",product.getId());
update.set("productName",product.getProductName());
update.set("productMoney",product.getProductMoney());
mongoTemplate.updateMulti(query,update,Product.class);
}
刪除
MongoTemplate的提供了remove
方法來進行刪除,當然基於刪除的操作也需要提供提供一個定位更新資料的Query
。MongoTemplate也提供了一個findAllAndRemove
發現並刪除的介面,當然我實際開發中此介面使用的並不算多。
@Override
public void deleteOneByTemplate(String id) {
Query query = new Query();
Criteria criteria = Criteria.where("id").is(id);
query.addCriteria(criteria);
mongoTemplate.remove(query,Product.class);
}
@Override
public void batchDeleteByTemplate(List<String> idList) {
Query query = new Query();
Criteria criteria = Criteria.where("id").in(idList);
query.addCriteria(criteria);
mongoTemplate.remove(query,Product.class);
}
查詢
MongoTemplate的查詢是使用findXXX
來實現的,核心的內容依舊是Query
。和使用MongoRepository不同,MongoTemplate沒有提供一個簡單的分頁查詢介面,需要根據先求總數然後獲取分頁資料。需要注意的是其分頁引數需要在Query
中設定,主要是skip
(起始行數)以及limit
(顯示行數)
@Override
public List<Product> queryByEntityByTemplate(Product product) {
Query query = new Query();
Criteria criteria = Criteria.byExample(Example.of(product));
query.addCriteria(criteria);
List<Product> products = mongoTemplate.find(query,Product.class);
return products;
}
@Override
public Page<Product> pageByEntityByTemplate(Product product,long startNum,int size) {
Query query = new Query();
Criteria criteria = Criteria.byExample(Example.of(product));
query.addCriteria(criteria);
long count = mongoTemplate.count(query,Product.class);
// 分頁引數
query.skip(startNum).limit(size);
List<Product> products = mongoTemplate.find(query,Product.class);
Page page = new PageImpl(products,Pageable.unpaged(),count);
return page;
}
個人水平有限,上面的內容可能存在沒有描述清楚或者錯誤的地方,假如開發同學發現了,請及時告知,我會第一時間修改相關內容,也希望大家看在這個新春佳節只能宅到家中埋頭苦逼的碼程式碼的情況下,能給我點一個贊。你的點贊就是我前進的動力。在這裡也祝大家新春快樂。