SpringBoot中MongoDB註解概念及使用
spring-data-mongodb主要有以下註解
@Id
主鍵,不可重複,自帶索引,可以在定義的列名上標註,需要自己生成並維護不重複的約束。如果自己不設定@Id主鍵,mongo會自動生成一個唯一主鍵,並且插入時效率遠高於自己設定主鍵。原因可參考上一篇mongo和mysql的效能對比。
在實際業務中不建議自己設定主鍵,應交給mongo自己生成,自己可以設定一個業務id,如int型欄位,用自己設定的業務id來維護相關聯的表。
@Document
標註在實體類上,類似於hibernate的entity註解,標明由mongo來維護該表。
org.springframework.data.mongodb.core.mapping.Document.class
把一個java類宣告為mongodb的文件,可以通過collection引數指定這個類對應的文件。
@Document (collection="mongodb 對應 collection 名")
// 若未加 @Document ,該 bean save 到 mongo 的 user collection
// 若新增 @Document ,則 save 到 reUser collection
@Document(collection="reUser")
public class User{
}
@Indexed
宣告該欄位需要加索引,加索引後以該欄位為條件檢索將大大提高速度。
唯一索引的話是@Indexed(unique = true)。
也可以對陣列進行索引,如果被索引的列是陣列時,MongoDB會索引這個陣列中的每一個元素。
也可以對整個Document進行索引,排序是預定義的按插入BSON資料的先後升序排列。
也可以對關聯的物件的欄位進行索引,譬如User對關聯的address.city進行索引。(註解怎麼寫還不清楚,待查)
@CompoundIndex
複合索引,加複合索引後通過複合索引欄位查詢將大大提高速度。
@Document
@CompoundIndexes({
@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
})
public class Person<T extends Address> {
}
寫法如上,lastName和age將作為複合索引,數字引數指定索引的方向,1為正序,-1為倒序。方向對單鍵索引和隨機存不要緊,但如果你要執行分組和排序操作的時候,它就非常重要了。
@Field
代表一個欄位,可以不加,不加的話預設以引數名為列名。
給對映儲存到 mongodb 的欄位取別名
在 java bean 中欄位名為 firstName,儲存到 mongo 中 key 為 fName
@Field("fName")
private String firstName;
@Transient
被該註解標註的,將不會被錄入到資料庫中。只作為普通的javaBean屬性。
@DBRef
關聯另一個document物件。類似於mysql的表關聯,但並不一樣,mongo不會做級聯的操作。
先來看一下不加DBRef時,mongo儲存資料的情況:
Article類有String title,List pictureList,兩個屬性,Picture有一個url,一個desc屬性。新建數個Picture物件,並賦值給Article的list,執行Article的insert操作,mongo儲存的結果如圖:
list會作為普通的資料存到article裡,並不會為Picture建表,這一點是區別於mysql的級聯儲存的。
在Article裡給list加上DBRef註解後就不同了
再次執行新增Article操作後,看結果
發現就不再是直接顯示的Picture的各個屬性了,而是隻儲存了Picture的id和namespace,同時仍然沒有建立Picture的collection(等同於mysql的表)。
如此此時查詢該Article,會發現list為空,並沒有關聯上Picture的值。其實上一步已經發現了,系統並沒有去建立Picture的表。那即便Article關聯了PictureList的id,也是無法查詢的。
官方解釋:
The mapping framework does not handle cascading saves. If you change an Account object that is referenced by a Person object, you must save the Account object separately. Calling save on the Person object will not automatically save the Account objects in the property accounts.意思就是不會處理級聯儲存,你必須單獨處理關聯的物件。
現在修改一下新增Article的程式碼,先做Picture的持久化操作。
再看結果,發現Picture已經被持久化,再次查詢該Article時,相應的Picture也全部查了出來。
如果在Article裡刪除關聯的list,set為null並儲存,系統只會刪掉Article裡關聯的list,而Picture物件本身的資料是不會被刪除的。
從上面看來,貌似DBRef比較雞肋,而且甚至有時還會帶著誤導的性質,譬如Article關聯了兩個空的Picture時在Article還能看到2個物件的引用,然後2個物件並不存在,是查詢不出來的。
那麼這個標籤存在的意義何在?官方的說法是:
In short,the best time to use DBRefs are when you’re storing heterogeneous references to documents in different collections.like when you want to take advantage of some additional DBRef-specific
functionality in a driver or tool.
實際使用中,感覺貌似作用是在不同的表做劃分吧,有點模擬mysql外來鍵的意思。免得資料都落到一個大表的,不便於做關聯的表的查詢。