MongoDB —— 使用Spring Data MongoDB操做數據庫

本文代碼示例參見:https://gitee.com/imlichao/MongoDB-examplehtml

 

咱們使用Spring Data MongoDB能夠方便的在Spring boot項目中操做MongoDBjava

文檔地址:https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-mongodbgit

加載包

在pom文件中加入spring-boot-starter-data-mongodb配置正則表達式

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

 

配置參數

# user - 用戶名、secret - 密碼、mongo1.example.com - 數據庫地址、27017- 端口號、teat - 庫名 
spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:27017/test

 

實體映射

咱們能夠經過實體類來進行關係映射,從而可以方便的使用對象進行數據操做。spring

Spring Data MongoDB提供了一些方便的映射註釋供咱們使用,下面列出官方說明地址以供參考mongodb

官方說明文檔:https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mapping-usage數據庫

  • @Id:用於標記id字段,沒有標記此字段的實體也會自動生成id字段,可是咱們沒法經過實體來獲取id。id建議使用ObjectId類型來建立。api

  • @Document:用於標記此實體類是mongodb集合映射類。可使用collection參數指定集合名稱。特別須要注意的是若是實體類沒有爲任何字段建立索引將不會自動建立集合。數組

  • @Indexed:用於標記爲某一字段建立索引。direction參數能夠指定排序方向,升或降序。oracle

  • @CompoundIndex:用於建立複合索引。def參數能夠定義複合索引的字段及排序方向。

  • @Transient:被該註解標註的,將不會被錄入到數據庫中。只做爲普通的javaBean屬性。

  • @PersistenceConstructor:用於聲明構造函數,做用是把從數據庫取出的數據實例化爲對象。

  • @Field:用於指定某一個字段映射到數據庫中的名稱。

  • @DBRef:用於指定與其餘集合的級聯關係,可是須要注意的是並不會自動建立級聯集合。

 

一個簡單的例子:

//註釋此類將被映射到數據庫的一個集合(collection爲集合名稱)
@Document(collection = "ex_entity_test")

//建立聯合索引
@CompoundIndexes({
        //聯合索引 name 索引名稱 、def 索引字段、parameter1升序、parameter3降序
        @CompoundIndex(name = "compound_index", def = "{'parameter1': 1, 'parameter3': -1}")
})

public class EntityTest implements Serializable {
    //標記id字段
    @Id
    private ObjectId id;
    //建立單字段索引(默認ASCENDING 升序、DESCENDING 降序)
    @Indexed(direction = DESCENDING)
    private Long parameter1;
    //修改映射到數據庫中的名稱
    @Field("parameter2_")
    private String parameter2;

    private Date parameter3;

    private Integer parameter4;

    //關聯其餘集合(不添加此註釋時List將會保存具體的實體值,而添加了此註釋List保存的是關聯集合的id)
    @DBRef
    private List<EntityTest1> parameter5;
    //此字段不映射到數據庫
    @Transient
    private Integer parameter6;

    public EntityTest(){

    }
    //聲明構造函數,用於實例化查詢結果數據
    @PersistenceConstructor
    public EntityTest(Long parameter1, String parameter2, Date parameter3, Integer parameter4, List<EntityTest1> parameter5) {
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
        this.parameter3 = parameter3;
        this.parameter4 = parameter4;
        this.parameter5 = parameter5;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    ......

    public Integer getParameter6() {
        return parameter6;
    }

    public void setParameter6(Integer parameter6) {
        this.parameter6 = parameter6;
    }
}

上例關聯的集合

//註釋此類將被映射到數據庫的一個集合(collection爲集合名稱)
@Document(collection = "ex_entity_test1")

public class EntityTest1 implements Serializable {
    //標記id字段
    @Id
    private ObjectId id;

    //若是實體類沒有爲任何字段建立索引將不會自動建立集合
    @Indexed
    private Long parameter1;

    public EntityTest1(){

    }

    public EntityTest1(Long parameter1) {
        this.parameter1 = parameter1;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public Long getParameter1() {
        return parameter1;
    }

    public void setParameter1(Long parameter1) {
        this.parameter1 = parameter1;
    }
}

 

數據操做

當完成一系列的配置與準備工做後,咱們就可使用MongoTemplate來操做數據庫了。

MongoTemplate爲咱們提供了全面的增刪改查等操做數據庫的方法,詳情可查看官方說明文檔和API文檔

官方說明文檔:https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mongo-template

API文檔:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html

一個簡單的例子:

@Controller
public class MongoController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @GetMapping(value = "/")
    public String index(){
        return "redirect:/find";
    }

    //新增文檔
    @GetMapping(value = "/insert")
    public String insert(){
        //insert方法並不提供級聯類的保存,因此級聯類須要先本身先保存
        EntityTest1 entityTest1_1 = new EntityTest1(1000L);
        //執行完insert後對象entityTest1將會得到保存後的id
        mongoTemplate.insert(entityTest1_1);
        //再添加一條
        EntityTest1 entityTest1_2 = new EntityTest1(1001L);
        mongoTemplate.insert(entityTest1_2);
        //建立列表並將保存後的關聯對象添加進去
        ArrayList<EntityTest1> entityTest1List = new ArrayList<EntityTest1>();
        entityTest1List.add(entityTest1_1);
        entityTest1List.add(entityTest1_2);

        //新增主體對象
        EntityTest entityTest = new EntityTest(100L,"test",new Date(),10,entityTest1List);
        //新增數據的主鍵已經存在,則會拋DuplicateKeyException異常
        mongoTemplate.insert(entityTest);
        return "redirect:/find";
    }

    //保存文檔
    //保存與新增的主要區別在於,若是主鍵已經存在,新增拋出異常,保存修改數據
    @GetMapping(value = "/save")
    public String save(){
        //查詢最後一條數據並更新
        Sort sort = new Sort(Sort.Direction.DESC,"parameter3");
        EntityTest entityTest = mongoTemplate.findOne(Query.query(Criteria.where("")).with(sort),EntityTest.class);
        entityTest.setParameter4(3000);
        //保存數據的主鍵已經存在,則會對已經存在的數據修改
        mongoTemplate.save(entityTest);
        return "redirect:/find";
    }

    //刪除文檔
    @GetMapping(value = "/delete")
    public String delete(){
        //查詢第一條數據並刪除
        EntityTest entityTest = mongoTemplate.findOne(Query.query(Criteria.where("")),EntityTest.class);
        //remove方法不支持級聯刪除因此要單獨刪除子數據
        List<EntityTest1> entityTest1List = entityTest.getParameter5();
        for(EntityTest1 entityTest1:entityTest1List){
            mongoTemplate.remove(entityTest1);
        }
        //刪除主數據
        mongoTemplate.remove(entityTest);

        return "redirect:/find";
    }

    //更新文檔
    @GetMapping(value = "/update")
    public String update(){
        //將查詢條件符合的所有文檔更新
        Query query = new Query();
        Update update = Update.update("parameter2_","update");
        mongoTemplate.updateMulti(query,update,EntityTest.class);
        return "redirect:/find";
    }

    //查詢文檔
    @GetMapping(value = "/find")
    public String find(Model model){
        //查詢小於當前時間的數據,並按時間倒序排列
        Sort sort = new Sort(Sort.Direction.DESC,"parameter3");
        List<EntityTest> findTestList = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort) ,EntityTest.class);
        model.addAttribute("findTestList",findTestList);

        //使用findOne查詢若是結果極爲多條,則返回排序在最上面的一條
        EntityTest findOneTest = mongoTemplate.findOne(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort) ,EntityTest.class);
        model.addAttribute("findOneTest",findOneTest);

        //模糊查詢
        List<EntityTest> findTestList1 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date()).and("parameter2").regex("es")) ,EntityTest.class);
        model.addAttribute("findTestList1",findTestList1);

        //分頁查詢(每頁3行第2頁)
        Pageable pageable = new PageRequest(1,3,sort);
        List<EntityTest> findTestList2 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(pageable) ,EntityTest.class);
        //共多少條
        Long count = mongoTemplate.count(Query.query(Criteria.where("parameter3").lt(new Date())),EntityTest.class);
        //返回分頁對象
        Page<EntityTest> page = new PageImpl<EntityTest>(findTestList2,pageable,count);
        model.addAttribute("page",page);

        //分頁查詢(經過起始行和數量也能夠本身實現分頁邏輯)
        List<EntityTest> findTestList3 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort).skip(3).limit(3) ,EntityTest.class);
        model.addAttribute("findTestList3",findTestList3);

        return "/index";
    }
}

 

查詢

因爲查詢相對於其餘增刪改的操做要複雜一些,因此在這裏單獨說一下查詢。還看上面的例子就能夠。

首先咱們先介紹一下幾個和查詢有關的類Query、Criteria、Sort、PageRequest、PageImpl

Query

查詢對象定義一個查詢的全部要素,其中包括篩選條件、排序、起始行、返回條數等內容

API文檔:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/Query.html

經常使用方法介紹:

query(CriteriaDefinition criteriaDefinition)

靜態方法經過注入一個CriteriaDefinition條件對象得到Query查詢對象。在簡單查詢時使用此方法將很是的方便。
例如:mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())

addCriteria(CriteriaDefinition criteriaDefinition)

添加一個CriteriaDefinition查詢條件類到本次查詢

skip(long skip)

跳過文檔的數量,能夠與limit配合使用實現分頁效果。

limit(int limit)

查詢返回的文檔數量。

with(Sort sort)

添加一個Sort排序對象

with(Pageable pageable)

添加一個Pageable分頁對象。Pageable能夠注入一個Sort,因此分頁和排序能夠一塊兒添加。
例如:Pageable pageable = new PageRequest(1,3,sort);

 

Criteria

查詢條件類,使用此類定義查詢時的查詢條件至關於SQL的where。

API文檔:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/Criteria.html

經常使用方法介紹:

where(String key)

靜態方法,用它能夠很方便的定義查詢條件

例如:mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date()).and("parameter2").regex("es"))

and(String key) 與操做
gt(Object o) 大於
gte(Object o) 大於等於
in(Object... o) 包含
is(Object o) 等於
lt(Object o) 小於
lte(Object o)    小於等於
not()
regex(String re) 正則表達式
andOperator(Criteria... criteria) 建立與操做
orOperator(Criteria... criteria) 建立或操做

 

Sort

查詢排序類,使用此類能夠建立查詢排序。

API文檔:https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Sort.html?is-external=true

經常使用方法介紹:

Sort(Sort.Direction direction, String... properties) 構造方法建立一個排序。direction爲排序方向的枚舉類型,properties爲排序字段數組
and(Sort sort) 多個排序條件連接
ascending() 返回升序排列對象
descending() 返回降序排列對象

 

PageRequest和PageImpl

這兩個類都是分頁相關的封裝類,與其餘數據庫的使用方法同樣。PageRequest分頁請求類,PageImpl爲頁面封裝類。

API文檔:https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html

               https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageImpl.html

相關文章
相關標籤/搜索