MongoDB:原來我如此簡單

為什麼要使用 MongoDB

  1. 張三大學畢業設計題目是《XXX部落格論壇》,他在存儲用戶評論的時候遇到了一個問題:這些評論數據量非常大,但是價值不是很大,如果存儲在 MySQL 資料庫中就會浪費性能。

  2. 李四在工作過程中遇到一個需求:在審批模組中,每一個公司都可以自定義請假類型,例如調休、出差等。相當於給每個公司維護一個自己的數據字典。

張三的痛點是存儲的部落格評論數據量大但是價值不大,不適合使用Mysql存儲。李四的痛點是需要維護一個數據字典,不適合用關係型數據局。為了解決張三和李四的痛點,這個時候非關係型文檔型資料庫 MongoDB 閃亮登場。

MongoDB 介紹

1. 什麼是 MongoDB

MongoDB是一個跨平台的,面向文檔的資料庫,是當前NoSQL資料庫產品中最熱門的一種。它介於關係資料庫和非關係資料庫之間,是非關係資料庫當中功能最豐富,最像關係資料庫的產品。

2. MongoDB 特點

MongoDB 最大的特點是他支援的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係資料庫單表查詢的絕大部分功能,而且還支援對數據建立索引。它是一個面向集合的,模式自由的文檔型資料庫。具體特點總結如下:
(1)面向集合存儲,易於存儲對象類型的數據
(2)模式自由
(3)支援動態查詢
(4)支援完全索引,包含內部對象
(5)支援複製和故障恢復
(6)使用高效的二進位數據存儲,包括大型對象(如影片等)
(7)支援 Python,Java,C,Javascript,Perl及 C++ 語言的驅動程式
(9)文件存儲格式為 BSON(一種 JSON 的擴展)

3. MongoDB 結構

MongoDB 的邏輯結構是一種層次結構。主要由:文檔 (document)、集合(collection)、資料庫 (database) 這三部分組成的。
(1)MongoDB 的文檔,相當於關係資料庫中的一行記錄。
(2)多個文檔組成一個集合,集合相當於關係資料庫的表。
(3)多個集合邏輯上組織在一起,就是資料庫。

4. MongoDB 與 MySQL 資料庫邏輯結構概念的對比

MongoDB MySQl
資料庫(database) 資料庫(database)
集合(Collection 表(table)
文檔(document) 行(row)
主鍵,MongoDB默認將_id設為主鍵 主鍵
索引 索引

5.MongoDB 層次結構如下圖

安裝 MongoDB

1. Docker安裝MongoDB

啟動MongoDB服務

 docker run -itd --name mongo -p 27017:27017 mongo --auth

註:1. 如果是購買的伺服器,請將安全組的27017埠打開。 2. -p 27017:27017 :容器服務的 27017 埠映射到伺服器的27017埠。外部可以直接通過伺服器 ip:27017 訪問到 mongodb 的服務。
–auth:需要密碼才能訪問。

2. 創建賬戶

##進入到容器內部
docker exec -it mongo mongo admin
##創建系統管理員
db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
##驗證賬戶密碼
db.auth('admin', '123456')

##創建其他資料庫
use ems
##在該資料庫下創建其他賬戶
db.createUser({ user: 'root', pwd: 'abc123456', roles: [ { role: "readWrite", db:"ems" } ] });
##驗證賬戶密碼
db.auth('root', 'abc123456')

3. Navicat 客戶端連接 MongoDB

創建資料庫

SpringBoot 整合 MongoDB

1. 添加依賴

<!-- MongoDB-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>        
</dependency>

2. 修改 SpringBoot 配置文件

spring:
  data:
    mongodb:
      uri: mongodb://root:123456@localhost:27017/test

賬戶:root
密碼:123456
資料庫:test

3. 創建實體類

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

/**
 * 常用收款人
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Document(collection = "common_account")
public class CommonAccount {
    @Id
    private String id;
    //公司id
    private Integer companyId;
    //付款人
    private String payer;
    //銀行
    private String bank;
    //分支行
    private String bankBranch;
    //帳號
    private String bankNum;
}

關鍵註解:1. @Document(collection = “common_account”)
@Document表示這是一個集合,當你保存數據的時候如果你沒有創建集合,他會自動給你創建一個名為 common_account 的集合。2. @Id:隨機生成id

4. 創建 Repository

@Repository
public interface CommonAccountRepository extends MongoRepository<CommonAccount, String> {

    //獲取該公司的所有常用收款人賬戶
    List<CommonAccount> getByCompanyId(Integer companyId);

}

extends MongoRepository:通過繼承 MongoRepository 可以使用它很多常用的方法。

5. 創建 Service

public interface CommonAccountService {

    //獲取該公司的收款賬戶
    List<CommonAccount> getCommonAccount(Integer companyId);

    //添加收款賬戶
    void addCommonAccount(CommonAccount commonAccount);

    //更新收款賬戶
    void updateCommonAccount(CommonAccount commonAccount);

    //刪除收款賬戶
    void deleteCommonAccount(String id);

}

6. Service 實現類

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class CommonAccountServiceImpl implements CommonAccountService {

    @Autowired
    private CommonAccountRepository commonAccountRepository;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public List<CommonAccount> getCommonAccount(Integer companyId) {
        List<CommonAccount> accountList = commonAccountRepository.getByCompanyId(companyId);
        return accountList;
    }

    @Override
    public void addCommonAccount(CommonAccount commonAccount) {
        commonAccountRepository.save(commonAccount);
    }

    @Override
    public void updateCommonAccount(CommonAccount commonAccount) {
        Query query = Query.query(Criteria.where("id").is(commonAccount.getId()));
        Update update = new Update();
        update.set("companyId", commonAccount.getCompanyId());
        update.set("payer", commonAccount.getPayer());
        update.set("bank", commonAccount.getBank());
        update.set("bankBranch", commonAccount.getBankBranch());
        update.set("bankNum", commonAccount.getBankNum());
        mongoTemplate.updateFirst(query, update, CommonAccount.class);
    }

    @Override
    public void deleteCommonAccount(String id) {
        commonAccountRepository.deleteById(id);
    }
}

7. 去除 _class 列

mongoDB 保存數據的時候默認會新增一個 _class 列,如下圖:

添加如下配置,去除_class 列

@Configuration
public class MongoConfig {

    /**
     * 去掉_class
     * @param factory
     * @param context
     * @param beanFactory
     * @return
     */
    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        try {
            mappingConverter.setCustomConversions(beanFactory.getBean(MongoCustomConversions.class));
        } catch (NoSuchBeanDefinitionException ignore) {
        }

        mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));

        return mappingConverter;
    }
}

8. 測試

    @Test
    void mongoTest() {
        CommonAccount commonAccount = new CommonAccount();
        commonAccount.setPayer("張三").setBank("交通銀行").setBankBranch("北京路分行")
                .setBankNum("61262663265362").setCompanyId(100);
        commonAccountService.addCommonAccount(commonAccount);
    }

Tags: