最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Data MongoDB的核心用法 附示例代碼

 更新時間:2026年02月27日 10:03:40   作者:沒有腰的嘟嘟嘟  
本文將系統(tǒng)梳理Spring Data MongoDB 的核心用法,涵蓋實體類注解、增刪改查、條件查詢、分頁排序等常見場景,并提供可直接復用的代碼示例,感興趣的朋友跟隨小編一起看看吧

 在使用 Spring Data MongoDB 操作 MongoDB 時,掌握實體映射規(guī)則與常用 CRUD 方法是開發(fā)高效應用的基礎。本文將系統(tǒng)梳理 Spring Data MongoDB 的核心用法,涵蓋實體類注解、增刪改查、條件查詢、分頁排序等常見場景,并提供可直接復用的代碼示例。

一、實體類與集合映射規(guī)則

  • 集合命名規(guī)則
    • 若實體類未使用 @Document 注解,則默認生成的集合名稱為首字母小寫的駝峰格式,且區(qū)分大小寫。
    • 例如:實體類名為 UserDao → 對應集合名為 userDao。
    • 使用 @Document(collection = "users") 可顯式指定集合名。
  • 主鍵標識
    • 使用 @Id 標注主鍵字段。
    • 若字段名為 id 或 _id,可省略 @Id 注解(Spring Data 會自動識別)。
  • 字段映射
    • 當 Java 字段名與 MongoDB 中的字段名不一致時,使用 @Field("db_field_name") 進行映射。
User user = new User("張三", 25);
User saved = mongoTemplate.insert(user); // 返回帶主鍵的對象

?? 注意:使用 mongoTemplate.insert() 插入數據時,MongoDB 會自動添加 _class 字段,存儲該文檔對應的 Java 類全限定名(如 com.example.User),用于反序列化時類型還原。

二、新增操作

User user = new User("張三", 25);
User saved = mongoTemplate.insert(user); // 返回帶主鍵的對象
  • 若集合不存在,會自動創(chuàng)建。
  • 自動注入 _class 字段。

三、修改操作

3.1 全量替換(慎用)

mongoTemplate.save(user); 

?? 此方法會完全覆蓋原文檔!即使只設置了部分字段,其他字段也會被置為 null。

3.2 局部更新(推薦)

Query query = Query.query(Criteria.where("id").is(userId));
Update update = new Update().set("name", "李四");
// 更新第一個匹配項
mongoTemplate.updateFirst(query, update, "userDao");
// 更新所有匹配項
mongoTemplate.updateMulti(query, update, "userDao");
  • Update.set() 對應 MongoDB 的 $set 操作符。
  • 第三個參數為集合名(非實體類名)。

四、刪除操作

// 1. 根據主鍵刪除(只需設置 id 字段)
User user = new User();
user.setId("60d..."); 
mongoTemplate.remove(user);
// 2. 根據條件刪除
Query query = Query.query(Criteria.where("age").lt(18));
mongoTemplate.remove(query, "userDao");

五、查詢操作

5.1 基礎查詢

// 查詢全部
List<User> all = mongoTemplate.findAll(User.class);
// 根據 ID 查詢
User user = mongoTemplate.findById("60d...", User.class);
// 查詢第一條匹配結果
User first = mongoTemplate.findOne(query, User.class);
// 查詢所有匹配結果
List<User> list = mongoTemplate.find(query, User.class);

5.2 條件查詢(Criteria)

判斷字段是否存在

// 等價于 db.user.find({name: {$exists: false}})
Query query = Query.query(Criteria.where("name").exists(false));

數值比較

含義MongoDB 操作符Spring Data 寫法
大于$gtCriteria.where("age").gt(18)
大于等于$gteCriteria.where("score").gte(90)
小于$ltCriteria.where("price").lt(100)
小于等于$lteCriteria.where("quantity").lte(5)

組合示例:

Query query = new Query(Criteria.where("age").gt(20).lt(30));
List<User> users = mongoTemplate.find(query, User.class);

模糊查詢(正則匹配)

// 包含匹配(任意位置)→ SQL: LIKE '%name%'
Query query = Query.query(Criteria.where("name").regex(Pattern.quote(name), "i"));
// 前綴匹配 → SQL: LIKE 'name%'
Query query = Query.query(Criteria.where("name").regex("^" + Pattern.quote(name), "i"));
// 后綴匹配 → SQL: LIKE '%name'
Query query = Query.query(Criteria.where("name").regex(Pattern.quote(name) + "$", "i"));

? 強烈建議使用 Pattern.quote() 轉義用戶輸入,防止正則注入!

去重查詢

Query query = Query.query(Criteria.where("name").regex("張"));
List<String> distinctNames = mongoTemplate.findDistinct(query, "name", User.class, String.class);

邏輯組合查詢

  • AND 查詢(姓名=張三 且 年齡>20):
Criteria criteria = Criteria.where("name").is("張三").and("age").gt(20);
Query query = Query.query(criteria);
  • OR 查詢(姓名=張三 或 年齡>20):
Criteria criteria = new Criteria().orOperator(
    Criteria.where("name").is("張三"),
    Criteria.where("age").gt(20)
);
Query query = Query.query(criteria);
  • 混合 AND/OR((張三 & 18歲) OR (李四 & 20歲))
Criteria and1 = Criteria.where("name").is("張三").and("age").is(18);
Criteria and2 = Criteria.where("name").is("李四").and("age").is(20);
Criteria or = new Criteria().orOperator(and1, and2);
List<User> result = mongoTemplate.find(Query.query(or), User.class);

5.3 排序

Query query = new Query(Criteria.where("age").gte(2));
query.with(Sort.by(Sort.Direction.DESC, "age")); // 按 age 降序
List<User> list = mongoTemplate.find(query, User.class);

5.4 分頁

// 第0頁(第一頁),每頁2條
Pageable pageable = PageRequest.of(0, 2);
Query query = new Query().with(pageable);
List<User> pageData = mongoTemplate.find(query, User.class);
// 分頁 + 排序
Pageable pageable = PageRequest.of(0, 2, Sort.by(Sort.Direction.ASC, "name"));

5.5 統(tǒng)計總數

TypedAggregation<User> agg = Aggregation.newAggregation(
    User.class,
    Aggregation.group().count().as("count")
);
AggregationResults<Map> result = mongoTemplate.aggregate(agg, Map.class);
Long total = (Long) result.getUniqueMappedResult().get("count");

5.6 帶條件的分組統(tǒng)計

TypedAggregation<User> agg = Aggregation.newAggregation(
    User.class,
    Aggregation.match(Criteria.where("name").is("張三")), // 先過濾
    Aggregation.group("name").count().as("count")        // 再分組
);
List<Map> results = mongoTemplate.aggregate(agg, Map.class).getMappedResults();
for (Map map : results) {
    System.out.println("姓名: " + map.get("_id") + ", 數量: " + map.get("count"));
}

?? Aggregation.match() 放在 group 前表示“先過濾后分組”,放在后面則是“先分組后過濾”。

六、常見問題與解決方案(FAQ)

在實際使用 Spring Data MongoDB 過程中,開發(fā)者常會遇到一些“坑”。以下是幾個高頻問題及其解決方法:

1.插入數據后集合中多出_class字段

問題現象
使用 mongoTemplate.insert() 插入文檔后,MongoDB 中自動多了一個 _class 字段,值為 Java 類的全限定名(如 com.example.User)。

原因
Spring Data MongoDB 默認啟用類型映射(Type Mapping),用于反序列化時確定目標 Java 類型。

解決方案

  • 方案一(推薦):若不需要類型信息,可在實體類上添加 @Document 并禁用 _class
@Document(collection = "users")
@TypeAlias("user") // 可選:用簡短別名替代全類名
public class User { ... }
  • 方案二(全局禁用):自定義 MongoCustomConversions,移除 _class 寫入(適用于所有實體):
@Configuration
public class MongoConfig {
    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions(Collections.emptyList());
    }
}

?? 注意:禁用后,若集合中存在多種類型文檔,反序列化可能失敗。

2.save()方法導致字段被置為 null

問題現象
調用 mongoTemplate.save(user) 更新對象時,未設置的字段在數據庫中被清空為 null。

原因
save() 是全量替換操作,不是局部更新。它會用傳入對象的當前狀態(tài)完全覆蓋原文檔。

解決方案
改用 updateFirst() 或 updateMulti() 做局部更新:

Query query = Query.query(Criteria.where("_id").is(userId));
Update update = new Update().set("name", "新名字").set("age", 30);
mongoTemplate.updateFirst(query, update, "users");

3.模糊查詢因特殊字符報錯或結果異常

問題現象
用戶輸入如 張*三、李.四 等包含正則元字符的內容進行模糊查詢時,拋出異常或匹配不到預期結果。

原因
regex() 直接將字符串當作正則表達式處理,而 *、.? 等是正則特殊字符。

解決方案
使用 Pattern.quote() 對輸入進行轉義:

String keyword = "張*三";
String escapedKeyword = Pattern.quote(keyword); // 轉義為字面量
Query query = Query.query(Criteria.where("name").regex(escapedKeyword, "i"));

? 同時建議加上 "i" 標志實現不區(qū)分大小寫匹配。

4.分頁查詢總數不準或性能差

問題現象
分頁時需要同時獲取總條數,但每次都要執(zhí)行一次 count 查詢,大數據量下響應慢。

原因
PageRequest 本身不包含總數,需額外調用 mongoTemplate.count(query, clazz)

解決方案

  • 小數據量:直接 count。
  • 大數據量/高并發(fā)
    • 使用緩存(如 Redis 緩存總數,定時刷新)。
    • 改用“游標分頁”(基于 _id 或時間戳的 gt/lt 查詢),避免深度分頁。
    • 示例(基于最后一條記錄的 _id 下一頁):
Query query = new Query(
    Criteria.where("_id").gt(lastId)
).limit(20).with(Sort.by(Sort.Direction.ASC, "_id"));

5.字段名不一致導致查不到數據

問題現象
Java 實體類字段為 userName,但數據庫中是 user_name,查詢返回 null 或空對象。

原因
未使用 @Field 注解建立映射關系。

解決方案
在實體類字段上顯式標注:

public class User {
    @Field("user_name")
    private String userName;
    @Field("created_at")
    private Date createdAt;
}

6.主鍵類型不匹配(String vs ObjectId)

問題現象
實體類主鍵為 String id,但 MongoDB 自動生成的是 ObjectId,導致 findById() 查不到數據。

原因
MongoDB 默認 _id 為 ObjectId,而 Java 用 String 接收時格式不匹配。

解決方案

  • 統(tǒng)一使用 String(推薦):插入時手動指定 _id 為字符串,或讓 Spring 自動轉換。
  • 或使用 ObjectId 類型:
import org.bson.types.ObjectId;
@Id
private ObjectId id;
  • 若堅持用 String,確保插入和查詢都使用相同格式(如 hex 字符串)。

7.聚合查詢返回空或類型轉換異常

問題現象
使用 aggregate() 后,getMappedResults() 返回空,或報 ClassCastException。

原因
聚合結果結構與接收類型(如 Map.class)不匹配,或字段名錯誤(如 _id 被重命名)。

解決方案

  • 打印原始結果調試:
AggregationResults<Document> raw = mongoTemplate.aggregate(agg, Document.class);
System.out.println(raw.getRawResults());
  • 確保 as("xxx") 的字段名與接收對象一致。
  • 若只取一個值,可用 getUniqueMappedResult();多個結果用 getMappedResults()。

到此這篇關于Spring Data MongoDB的核心用法 附示例代碼的文章就介紹到這了,更多相關spring data mongodb用法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Flowable 設置流程變量的四種方式詳解

    Flowable 設置流程變量的四種方式詳解

    這篇文章主要為大家介紹了Flowable 設置流程變量的四種方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • SpringBoot引入額外的YAML配置文件的代碼實現

    SpringBoot引入額外的YAML配置文件的代碼實現

    在SpringBoot項目中,有時需要引入除application.yml之外的配置文件(例如在開發(fā)公共組件時),使用@PropertySource注解可以實現這一需求,但有一些細節(jié)點需要注意,在此記錄,感興趣的小伙伴跟著小編一起來看看吧
    2024-09-09
  • java實現List中對象排序的方法

    java實現List中對象排序的方法

    這篇文章主要介紹了java實現List中對象排序的方法,涉及Java中的遍歷與對象操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • javaWeb使用驗證碼實現簡單登錄

    javaWeb使用驗證碼實現簡單登錄

    這篇文章主要為大家詳細介紹了javaWeb使用驗證碼實現簡單登錄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Java通過SSLEngine與NIO實現HTTPS訪問的操作方法

    Java通過SSLEngine與NIO實現HTTPS訪問的操作方法

    這篇文章主要介紹了Java通過SSLEngine與NIO實現HTTPS訪問,需要在Connect操作、Connected操作、Read和Write操作中加入SSL相關的處理即可,需要的朋友可以參考下
    2021-08-08
  • Java zookeeper圖形化工具ZooInspector用法詳解

    Java zookeeper圖形化工具ZooInspector用法詳解

    這篇文章主要介紹了Java zookeeper圖形化工具ZooInspector用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • SpringBoot使用Mybatis-Generator配置過程詳解

    SpringBoot使用Mybatis-Generator配置過程詳解

    這篇文章主要介紹了SpringBoot使用Mybatis-Generator配置過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot實現日志鏈路追蹤的項目實踐

    SpringBoot實現日志鏈路追蹤的項目實踐

    在分布式系統(tǒng)中,由于請求的處理過程可能會跨越多個服務,因此,對請求的追蹤變得尤為重要,本文主要介紹了SpringBoot實現日志鏈路追蹤的項目實踐,感興趣的可以了解一下
    2024-03-03
  • Java如何基于command調用openssl生成私鑰證書

    Java如何基于command調用openssl生成私鑰證書

    這篇文章主要介紹了Java如何基于command調用openssl生成私鑰證書,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java批量實現將Word文檔高效轉換為多頁TIFF圖片

    Java批量實現將Word文檔高效轉換為多頁TIFF圖片

    在日常辦公或文檔管理中,我們經常會遇到需要轉換 Word 文檔,本文將詳細講解如何使用 Java 將 Word 文檔轉換為 TIFF 圖片,包括單文件轉換、批量轉換以及轉換特定節(jié)的示例,有需要的小伙伴可以了解下
    2026-03-03

最新評論

遂宁市| 安泽县| 怀宁县| 舒兰市| 蒲江县| 渝北区| 武鸣县| 柳江县| 金湖县| 苍南县| 枝江市| 勃利县| 大安市| 辽中县| 昂仁县| 保定市| 右玉县| 淳安县| 平塘县| 韶关市| 兴隆县| 衡阳市| 兖州市| 临漳县| 文登市| 察隅县| 什邡市| 门源| 双流县| 辽阳市| 金乡县| 河间市| 都昌县| 丹棱县| 岚皋县| 江都市| 固始县| 隆安县| 沙洋县| 马山县| 高安市|