springboot2.X 使用spring-data組件對MongoDB做CURD

  • 2019 年 10 月 3 日
  • 筆記

springboot2.X 使用spring-data組件對MongoDB做CURD

使用背景

基於快速開發,需求不穩定的情況, 我決定使用MongoDB作為存儲資料庫,搭配使用spring-data

因為快速開發,使用spring data可以直接在類上建表等其他操作,而且對於複合數據模型,MongoDB可以直接存儲

程式碼地址

gitee

github

入門普通級別

1.引入maven依賴

<dependencies>          <!--###############時間日期操作################-->          <dependency>              <groupId>joda-time</groupId>              <artifactId>joda-time</artifactId>          </dependency>              <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-data-mongodb</artifactId>          </dependency>            <dependency>              <groupId>cn.hutool</groupId>              <artifactId>hutool-all</artifactId>          </dependency>            <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter</artifactId>          </dependency>          <!--###############springboot-aop模組################-->          <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-aop</artifactId>          </dependency>          <!--###############test模組################-->          <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-test</artifactId>              <scope>test</scope>          </dependency>          <!--###############web模組################-->          <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <!--###############lombok################-->          <dependency>              <groupId>org.projectlombok</groupId>              <artifactId>lombok</artifactId>          </dependency>            <!--fast json-->          <dependency>              <groupId>com.alibaba</groupId>              <artifactId>fastjson</artifactId>          </dependency>            <dependency>              <groupId>com.google.guava</groupId>              <artifactId>guava</artifactId>          </dependency>    </dependencies>

基於maven dependencyManagement 版本控制如下:

    <dependencyManagement>          <dependencies>              <dependency>                  <groupId>org.springframework.boot</groupId>                  <artifactId>spring-boot-dependencies</artifactId>                  <version>2.1.2.RELEASE</version>                  <type>pom</type>                  <scope>import</scope>              </dependency>                <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->              <dependency>                  <groupId>mysql</groupId>                  <artifactId>mysql-connector-java</artifactId>                  <version>5.1.48</version>              </dependency>                <dependency>                  <groupId>cn.hutool</groupId>                  <artifactId>hutool-all</artifactId>                  <version>4.5.16</version>              </dependency>                <!--mybatis-->              <dependency>                  <groupId>org.mybatis.spring.boot</groupId>                  <artifactId>mybatis-spring-boot-starter</artifactId>                  <version>2.0.0</version>              </dependency>                <!--fast json-->              <dependency>                  <groupId>com.alibaba</groupId>                  <artifactId>fastjson</artifactId>                  <version>1.2.56</version>              </dependency>                <!-- druid -->              <dependency>                  <groupId>com.alibaba</groupId>                  <artifactId>druid-spring-boot-starter</artifactId>                  <version>1.1.9</version>              </dependency>                <dependency>                  <groupId>com.google.guava</groupId>                  <artifactId>guava</artifactId>                  <version>19.0</version>              </dependency>          </dependencies>      </dependencyManagement>  

2.使用docker啟動MongoDB

docker run --restart="always"             -d             --name mongo            -p 27017:27017            -v /docker/mongo/data/db:/data/db            mongo:latest --storageEngine wiredTiger 

3.創建Mongo的實體類

  • @Document(collection="female")

  • 設置id: @Id

  • 設置屬性

  • 構建索引

  • getter/setter

Female.java

@Document(collection = "female")  @Data  public class Female {      /**       * 主鍵       */      @Id      private String id;        /**       * 姓名       */      private String name;        /**       * 年齡       */      private String age;        /**       * 哪種類型的女人;FemaleTypeEnums       */      private Integer type;        /**       * 舔狗       */      private List<Male> dogs;        /**       * 男朋友們       */      @Indexed      private List<Male> boyFriends;        /**       * 男神們       */      @Indexed      private List<Male> dreamers;        /**       * 創建時間       */      @Indexed      private Date createTime;        /**       * 修改時間       */      private Date modifiedTime;  }

4.創建Dao層

  • 創建Repository 繼承於MongoRepository

  • 根據規則來編寫介面方法, spring data mongodb的dao 方法規則詳細查看點這裡,理論上用idea會提示出來的.

  • 編寫單元測試方法

創建Repository 繼承於MongoRepository,編寫介面方法

FemaleRepository.java

public interface FemaleRepository extends MongoRepository<Female,String> {      Page<Female> findAllByCreateTimeBetweenAndNameContaining(Date createTime, Date createTime2, String name, Pageable pageable);        Page<Female> findAllByCreateTimeBefore(Date createTime, Pageable pageable);        Page<Female> findAllByCreateTimeAfter(Date createTime, Pageable pageable);        Page<Female> findAllByCreateTimeBetween(Date start, Date end, PageRequest pageRequest);  }

單元測試方法

FemaleRepositoryTest.java

    /**       * description: 添加測試數據       * author: suwenguang       * date: 2019-09-01       */      @Test      public void addTestData() {          for (int i = 0; i < 1000; i++) {              Female entity = new Female();              entity.setName(RandomUtil.randomString(12));              LocalDate now = LocalDate.now();              LocalDate localDate = now.minusDays(RandomUtil.randomInt(4));              entity.setCreateTime(localDate.toDate());              femaleRepository.save(entity);          }      }        /**       * description: 測試查詢構造器       * author: suwenguang       * date: 2019-09-01       */      public void  matching(){          //精確匹配和模糊匹配          Female probe = new Female();          ExampleMatcher matching = ExampleMatcher.matching()              .withMatcher("name", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.CONTAINING))//模糊匹配              .withIgnorePaths("id")//忽略匹配id              ;          PageRequest of = PageRequest.of(0, 10);          Page<Female> all = femaleRepository.findAll(Example.of(probe, matching), of);          System.out.println(JSON.toJSONString(all));      }        /**       * description: 測試範圍查詢       * author: suwenguang       * date: 2019-09-01       */      @Test      public void findAllByCreateTimeAfter() {          LocalDate yesteday = new LocalDate().minusDays(3);          PageRequest of = PageRequest.of(0, 10);          List<Female> byCreateTimeAfter = femaleRepository.findAllByCreateTimeAfter(yesteday.toDate(), of);          System.out.println(JSON.toJSONString(byCreateTimeAfter));      }        /**       * description: 測試範圍查詢       * author: suwenguang       * date: 2019-09-01       */      @Test      public void findByCreateTimeBetween() {          LocalDate localDate = new LocalDate();          Page<Female> byCreateTimeBetween = femaleRepository.findByCreateTimeBetween(localDate.minusDays(2).toDate(), localDate.toDate(), PageRequest.of(0, 10));          System.out.println(JSON.toJSONString(byCreateTimeBetween.getContent()));      }

進階Querydsl擴展複雜查詢

(基於單表的複雜查詢,多表複雜查詢暫時不納入討論範圍)

如果按照以上的用法,動態擴展多條件查詢仍然不能夠完美支援,會導致程式碼冗餘,當然你如果使用mongoTemlate進行自己封裝,另當別論.

那麼為了實現動態擴展多條件查詢,我去查看對應版本的官方文檔,跳轉點這裡,看到可以集成querydsl作為擴展.

步驟

  • 整合querydsl

  • 使用dsl

1.整合querydsl

1.Querydsl官網

2.querydsl集成文檔

pom.xml配置引入依賴

       <!--###############複雜查詢querydsl jpa################-->          <dependency>              <groupId>com.querydsl</groupId>              <artifactId>querydsl-apt</artifactId>              <version>${querydsl.version}</version>              <scope>provided</scope>          </dependency>            <dependency>              <groupId>com.querydsl</groupId>              <artifactId>querydsl-jpa</artifactId>              <version>${querydsl.version}</version>          </dependency>    <!--        <dependency>-->  <!--            <groupId>org.slf4j</groupId>-->  <!--            <artifactId>slf4j-log4j12</artifactId>-->  <!--            <version>1.6.1</version>-->  <!--        </dependency>-->

為什麼要注釋掉slf4j?

因為我的springboot項目已經引入了slf4j,沒必要重複聲明,自己可以通過idea的maven dependence查看是否有引入,沒有則需要重新引入

2.使用dsl

  • daorepository中繼承QuerydslPredicateExecutor<T>

    public interface FemaleRepository extends MongoRepository<Female,String>, QuerydslPredicateExecutor<Female> {    }
  • 編寫單元測試FemaleRepositoryTest.java

      /**     * description: 多條件     * author: suwenguang     * date: 2019-09-01     */    @Test    public void querydsl() {        PageRequest of = PageRequest.of(0, 10);        QFemale female = QFemale.female;        BooleanExpression createTimeBetween = female.createTime.between(LocalDate.now().minusDays(2).toDate(), LocalDate.now().minusDays(1).toDate());        BooleanBuilder builder = new BooleanBuilder(createTimeBetween);        BooleanExpression contains = female.name.contains("3");        builder.and(contains);        Page<Female> all = femaleRepository.findAll(builder,of);        System.out.println(all.getTotalElements());        System.out.println(JSON.toJSONString(all.getContent()));    }

如上所示, 這樣子可以動態構造所需要的條件,多個範圍查詢也可以支援了!!!那麼對於後台的搜索數據只需要一個介面就可以了

至於怎麼實現,後面再繼續整合 X-admin 2.2這個後端模板, 另外出一篇文章吧.

如果對上訴程式碼有問題或者有其他的擴展性問題,歡迎留下你的評論.

補充

  • BooleanBuilder的類圖, 可以通過idea查看,因為findAll是通過父類繼承下來的介面, 裡面的Predicate也是一個介面,而BooleanExpression和BooleanBuilder都是實現了Predicate的;