springboot2.X 使用spring-data組件對MongoDB做CURD
- 2019 年 10 月 3 日
- 筆記
springboot2.X 使用spring-data組件對MongoDB做CURD
使用背景
基於快速開發,需求不穩定的情況, 我決定使用MongoDB作為存儲資料庫,搭配使用spring-data
因為快速開發,使用spring data可以直接在類上建表等其他操作,而且對於複合數據模型,MongoDB可以直接存儲
程式碼地址
入門普通級別
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
@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,編寫介面方法
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); }
單元測試方法
/** * 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
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
-
在
dao
的repository
中繼承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的;