Spring Boot 中使用 MongoDB 增刪改查

搜雲庫技術團隊發表於2018-02-05

本文快速入門,MongoDB 結合SpringBoot starter-data-mongodb 進行增刪改查

1、什麼是MongoDB ?

MongoDB 是由C++語言編寫的,是一個基於分散式檔案儲存的開源資料庫系統。

在高負載的情況下,新增更多的節點,可以保證伺服器效能。

MongoDB 旨在為WEB應用提供可擴充套件的高效能資料儲存解決方案。

MongoDB 將資料儲存為一個文件,資料結構由鍵值(key=>value)對組成。

MongoDB 文件類似於 JSON 物件。欄位值可以包含其他文件,陣列及文件陣列。

2、MongoDB 優缺點

優點

  • 文件結構的儲存方式,能夠更便捷的獲取資料
  • 內建GridFS,支援大容量的儲存
  • 海量資料下,效能優越
  • 動態查詢
  • 全索引支援,擴充套件到內部物件和內嵌陣列
  • 查詢記錄分析
  • 快速,就地更新
  • 高效儲存二進位制大物件 (比如照片和視訊)
  • 複製(複製集)和支援自動故障恢復
  • 內建 Auto- Sharding 自動分片支援雲級擴充套件性,分片簡單
  • MapReduce 支援複雜聚合
  • 商業支援,培訓和諮詢

缺點

  • 不支援事務操作
  • MongoDB 佔用空間過大 (不過這個確定對於目前快速下跌的硬碟價格來說,也不算什麼缺點了)
  • MongoDB沒有如MySQL那樣成熟的維護工具
  • 無法進行關聯表查詢,不適用於關係多的資料
  • 複雜聚合操作通過mapreduce建立,速度慢
  • 模式自由,自由靈活的檔案儲存格式帶來的資料錯
  • MongoDB 在你刪除記錄後不會在檔案系統回收空間。除非你刪掉資料庫。但是空間沒有被浪費

3、優缺點詳細解釋

1.內建GridFS,支援大容量的儲存:

GridFS是一個出色的分散式檔案系統,可以支援海量的資料儲存。 內建了GridFS了MongoDB,能夠滿足對大資料集的快速範圍查詢。

2.內建 Auto- Sharding 自動分片支援雲級擴充套件性,分片簡單

提供基於Range的Auto Sharding機制:

一個collection可按照記錄的範圍,分成若干個段,切分到不同的Shard上。

Shards可以和複製結合,配合Replica sets能夠實現Sharding+fail-over,不同的Shard之間可以負載均衡。
查詢是對客戶端是透明的。客戶端執行查詢,統計,MapReduce等操作,這些會被MongoDB自動路由到後端的資料節點。
這讓我們關注於自己的業務,適當的 時候可以無痛的升級。MongoDB的Sharding設計能力最大可支援約20 petabytes,足以支撐一般應用。
這可以保證MongoDB執行在便宜的PC伺服器叢集上。PC叢集擴充起來非常方便並且成本很低,避免了“sharding”操作的複雜性和成本。

3.海量資料下,效能優越:

在使用場合下,千萬級別的文件物件,近10G的資料,對有索引的ID的查詢不會比mysql慢,而對非索引欄位的查詢,則是全面勝出。 mysql實際無法勝任大資料量下任意欄位的查詢,而mongodb的查詢效能實在讓我驚訝。寫入效能同樣很令人滿意,同樣寫入百萬級別的數 據,mongodb比我以前試用過的couchdb要快得多,基本10分鐘以下可以解決。補上一句,觀察過程中mongodb都遠算不上是CPU殺手。

4.全索引支援,擴充套件到內部物件和內嵌陣列

索引通常能夠極大的提高查詢的效率,如果沒有索引,MongoDB在讀取資料時必須掃描集合中的每個檔案並選取那些符合查詢條件的記錄。

這種掃描全集合的查詢效率是非常低的,特別在處理大量的資料時,查詢可以要花費幾十秒甚至幾分鐘,這對網站的效能是非常致命的。

索引是特殊的資料結構,索引儲存在一個易於遍歷讀取的資料集合中,索引是對資料庫表中一列或多列的值進行排序的一種結構。

5.MapReduce 支援複雜聚合

MongoDB中聚合(aggregate)主要用於處理資料(諸如統計平均值,求和等),並返回計算後的資料結果。有點類似sql語句中的 count(*)。

與關係型資料庫相比,MongoDB的缺點:

mongodb不支援事務操作:

所以事務要求嚴格的系統(如果銀行系統)肯定不能用它。

mongodb不支援事務操作:

所以事務要求嚴格的系統(如果銀行系統)肯定不能用它。

mongodb佔用空間過大:

關於其原因,在官方的FAQ中,提到有如下幾個方面:

1、空間的預分配:為避免形成過多的硬碟碎片,mongodb每次空間不足時都會申請生成一大塊的硬碟空間,而且申請的量從64M、128M、256M那 樣的指數遞增,直到2G為單個檔案的最大體積。隨著資料量的增加,你可以在其資料目錄裡看到這些整塊生成容量不斷遞增的檔案。

2、欄位名所佔用的空間:為了保持每個記錄內的結構資訊用於查詢,mongodb需要把每個欄位的key-value都以BSON的形式儲存,如果 value域相對於key域並不大,比如存放數值型的資料,則資料的overhead是最大的。一種減少空間佔用的方法是把欄位名儘量取短一些,這樣佔用 空間就小了,但這就要求在易讀性與空間佔用上作為權衡了。

3、刪除記錄不釋放空間:這很容易理解,為避免記錄刪除後的資料的大規模挪動,原記錄空間不刪除,只標記“已刪除”即可,以後還可以重複利用。

4、可以定期執行db.repairDatabase()來整理記錄,但這個過程會比較緩慢

MongoDB沒有如MySQL那樣成熟的維護工具,這對於開發和IT運營都是個值得注意的地方。

4、環境需要

64位作業系統,建議使用Linux / Unix /

  • CentOs 7.3
  • MongoDB 3.6.2

5、環境安裝

請參考我的另一篇文章

搭建 MongoDB分片(sharding) / 分割槽 / 叢集環境

www.ymq.io/2018/01/30/…

6、新加專案

新建一個 maven 專案,這裡就不詳細操作了,大家都會的

不過也可以下載我的示例原始碼,下載地址如下

GitHub:github.com/souyunku/sp…

碼雲:gitee.com/souyunku/sp…

MongoDB是一個開源NoSQL文件資料庫,它使用類似JSON的模式而不是傳統的基於表格的關係資料。Spring Boot為MongoDB提供了一些便利,包括 spring-boot-starter-data-mongodb “Starter”。

7、新增依賴

在POM 中新增如下依賴

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
複製程式碼

8、配置檔案

在配置檔案 application.properties 新增如下配置

spring.application.name=spring-boot-mongodb
# mongodb
spring.data.mongodb.uri=mongodb://192.168.252.121:20000,192.168.252.122:20000,192.168.252.12:20000/demo
複製程式碼

多個IP叢集的配置:

spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test
複製程式碼

9、DemoEntity

spring-data-mongodb中的實體對映是通過MongoMappingConverter這個類實現的。它可以通過註釋把java類轉換為mongodb的文件。

它有以下幾種註釋:

@Id - 文件的唯一標識,在mongodb中為ObjectId,它是唯一的,通過時間戳+機器標識+程式ID+自增計數器(確保同一秒內產生的Id不會衝突)構成。

@Document - 把一個java類宣告為mongodb的文件,可以通過collection引數指定這個類對應的文件。@Document(collection="mongodb") mongodb對應表

@DBRef - 宣告類似於關聯式資料庫的關聯關係。ps:暫不支援級聯的儲存功能,當你在本例項中修改了DERef物件裡面的值時,單獨儲存本例項並不能儲存DERef引用的物件,它要另外儲存,如下面例子的Person和Account。

@Indexed - 宣告該欄位需要索引,建索引可以大大的提高查詢效率。

@CompoundIndex - 複合索引的宣告,建複合索引可以有效地提高多欄位的查詢效率。

@GeoSpatialIndexed - 宣告該欄位為地理資訊的索引。

@Transient - 對映忽略的欄位,該欄位不會儲存到mongodb。

@PersistenceConstructor - 宣告建構函式,作用是把從資料庫取出的資料例項化為物件。該建構函式傳入的值為從DBObject中取出的資料

package io.ymq.example.mongodb;

@Document(collection = "demo_collection")
public class DemoEntity implements Serializable {

    @Id
    private Long id;

    private String title;

    private String description;

    private String by;

    private String url;
	
	省略 getter setter
}
複製程式碼

10、Demo DAO 介面

提供增刪改查 MongoDB 介面

package io.ymq.example.mongodb;

public interface DemoDao {

    void saveDemo(DemoEntity demoEntity);

    void removeDemo(Long id);

    void updateDemo(DemoEntity demoEntity);

    DemoEntity findDemoById(Long id);
}
複製程式碼

11、Demo DAO 實現

提供增刪改查 MongoDB 介面實現

Spring Data Mongo提供了一個 MongoTemplate類似於Spring的設計的類JdbcTemplate。和JdbcTemplateSpring Boot一樣,自動配置一個bean來簡單地注入:

package io.ymq.example.mongodb;

/**
 * 描述: Demo DAO 實現
 *
 * @author yanpenglei
 * @create 2018-02-03 16:57
 **/
@Component
public class DemoDaoImpl implements DemoDao {

    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public void saveDemo(DemoEntity demoEntity) {
        mongoTemplate.save(demoEntity);
    }

    @Override
    public void removeDemo(Long id) {
        mongoTemplate.remove(id);
    }

    @Override
    public void updateDemo(DemoEntity demoEntity) {
        Query query = new Query(Criteria.where("id").is(demoEntity.getId()));

        Update update = new Update();
        update.set("title", demoEntity.getTitle());
        update.set("description", demoEntity.getDescription());
        update.set("by", demoEntity.getBy());
        update.set("url", demoEntity.getUrl());

        mongoTemplate.updateFirst(query, update, DemoEntity.class);
    }

    @Override
    public DemoEntity findDemoById(Long id) {
        Query query = new Query(Criteria.where("id").is(id));
        DemoEntity demoEntity = mongoTemplate.findOne(query, DemoEntity.class);
        return demoEntity;
    }

}
複製程式碼

12、啟動服務

執行啟動類

package io.ymq.example.mongodb;

@SpringBootApplication
public class SpringBootMongodbApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootMongodbApplication.class, args);
    }
}
複製程式碼

13、單元測試

單元測試,提供mongodbdemo 庫的 demo_collection 集合的增刪改查

package io.ymq.example.mongodb;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootMongodbApplication.class)
public class SpringBootMongodbApplicationTests {

    @Autowired
    private DemoDao demoDao;

    @Test
    public void saveDemoTest() {

        DemoEntity demoEntity = new DemoEntity();
        demoEntity.setId(1L);
        demoEntity.setTitle("Spring Boot 中使用 MongoDB");
        demoEntity.setDescription("關注公眾號,搜雲庫,專注於開發技術的研究與知識分享");
        demoEntity.setBy("souyunku");
        demoEntity.setUrl("http://www.souyunku.com");

        demoDao.saveDemo(demoEntity);

        demoEntity = new DemoEntity();
        demoEntity.setId(2L);
        demoEntity.setTitle("Spring Boot 中使用 MongoDB");
        demoEntity.setDescription("關注公眾號,搜雲庫,專注於開發技術的研究與知識分享");
        demoEntity.setBy("souyunku");
        demoEntity.setUrl("http://www.souyunku.com");

        demoDao.saveDemo(demoEntity);
    }

    @Test
    public void removeDemoTest() {
        demoDao.removeDemo(2L);
    }

    @Test
    public void updateDemoTest() {

        DemoEntity demoEntity = new DemoEntity();
        demoEntity.setId(1L);
        demoEntity.setTitle("Spring Boot 中使用 MongoDB 更新資料");
        demoEntity.setDescription("關注公眾號,搜雲庫,專注於開發技術的研究與知識分享");
        demoEntity.setBy("souyunku");
        demoEntity.setUrl("http://www.souyunku.com");

        demoDao.updateDemo(demoEntity);
    }

    @Test
    public void findDemoByIdTest() {

        DemoEntity demoEntity = demoDao.findDemoById(1L);

        System.out.println(JSONObject.toJSONString(demoEntity));
    }
}
複製程式碼

擴充套件閱讀

手把手教你 MongoDB 的安裝與詳細使用(一)

www.ymq.io/2018/01/26/…

手把手教你 MongoDB 的安裝與詳細使用(二)

www.ymq.io/2018/01/29/…

原始碼下載

GitHub:github.com/souyunku/sp…

碼雲:gitee.com/souyunku/sp…

福利

Spring Boot 學習教程 會不定時更新技術, 歡迎 Star 和 Fork。

github.com/souyunku/sp…

github.com/souyunku/sp…

參考:docs.spring.io/spring-boot…

Contact

關注公眾號-搜雲庫
搜雲庫

相關文章