這裡我們用到的是spring-data中一個整合mongodb的專案,首先在maven中新增對它的依賴,這裡我用的是1.0.0.M5版本
3 |
< groupId >org.springframework.data</ groupId > |
4 |
< artifactId >spring-data-mongodb</ artifactId > |
5 |
< version >1.0.0.M5</ version > |
然後是配置檔案
01 |
<? xml version = "1.0" encoding = "UTF-8" ?> |
02 |
< beans xmlns = "http://www.springframework.org/schema/beans" |
03 |
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:context = "http://www.springframework.org/schema/context" |
04 |
xmlns:mongo = "http://www.springframework.org/schema/data/mongo" |
05 |
xsi:schemaLocation="http://www.springframework.org/schema/context |
06 |
http://www.springframework.org/schema/context/spring-context-3.0.xsd |
07 |
http://www.springframework.org/schema/data/mongo |
08 |
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd |
09 |
http://www.springframework.org/schema/beans |
10 |
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
11 |
< context:property-placeholder location = "classpath*:META-INF/mongodb/mongodb.properties" /> |
14 |
< mongo:mongo id = "mongo" replica-set = "localhost:27017" > |
17 |
connections-per-host = "${mongo.connectionsPerHost}" |
18 |
threads-allowed-to-block-for-connection-multiplier = "${mongo.threadsAllowedToBlockForConnectionMultiplier}" |
19 |
connect-timeout = "${mongo.connectTimeout}" |
20 |
max-wait-time = "${mongo.maxWaitTime}" |
21 |
auto-connect-retry = "${mongo.autoConnectRetry}" |
22 |
socket-keep-alive = "${mongo.socketKeepAlive}" |
23 |
socket-timeout = "${mongo.socketTimeout}" |
24 |
slave-ok = "${mongo.slaveOk}" |
31 |
< mongo:db-factory dbname = "test" mongo-ref = "mongo" /> |
34 |
< bean id = "mongoTemplate" class = "org.springframework.data.mongodb.core.MongoTemplate" > |
35 |
< constructor-arg name = "mongoDbFactory" ref = "mongoDbFactory" /> |
39 |
< mongo:mapping-converter base-package = "com.xxx.xxx.domain" /> |
42 |
< mongo:repositories base-package = "com.xxx.xxx.persist.mongodb" /> |
45 |
< context:annotation-config /> |
這樣基本配置就完成了
spring-data-mongodb中的實體對映是通過
MongoMappingConverter這個類實現的。它可以通過註釋把
java類轉換為mongodb的文件。
它有以下幾種註釋:
@Id - 文件的唯一標識,在mongodb中為ObjectId,它是唯一的,通過時間戳+機器標識+程式ID+自增計數器(確保同一秒內產生的Id不會衝突)構成。
@Document - 把一個java類宣告為mongodb的文件,可以通
過collection引數指定這個類對應的文件。
@DBRef - 宣告類似於關聯式資料庫的關聯關係。ps:暫不支援級聯的儲存功能,當你在本例項中修改了DERef物件裡面的值時,單獨儲存本例項並不能儲存DERef引用的物件,它要另外儲存,如下面例子的Person和Account。
@Indexed - 宣告該欄位需要索引,建索引可以大大的提高查詢效率。
@CompoundIndex - 複合索引的宣告,建複合索引可以有效地提高多欄位的查詢效率。
@GeoSpatialIndexed - 宣告該欄位為地理資訊的索引。
@Transient - 對映忽略的欄位,該欄位不會儲存到
mongodb。
@PersistenceConstructor - 宣告建構函式,作用是把從資料庫取出的資料例項化為物件。該建構函式傳入的值為從DBObject中取出的資料。
以下引用一個官方文件的例子:
Person類
01 |
@Document (collection= "person" ) |
03 |
@CompoundIndex (name
= "age_idx" ,
def = "{'lastName':
1, 'age': -1}" ) |
05 |
public class Person<T extends Address>
{ |
09 |
@Indexed (unique
= true ) |
11 |
private String
firstName; |
13 |
private String
lastName; |
16 |
private Integer
accountTotal; |
18 |
private List<Account>
accounts; |
22 |
public Person(Integer
ssn) { |
26 |
@PersistenceConstructor |
27 |
public Person(Integer
ssn, String firstName, String lastName, Integer age, T address) { |
29 |
this .firstName
= firstName; |
30 |
this .lastName
= lastName; |
32 |
this .address
= address; |
Account類
與HibernateRepository類似,通過繼承MongoRepository介面,我們可以非常方便地實現對一個物件的增刪改查,要使用Repository的功能,先繼承MongoRepository<T, TD>介面,其中T為倉庫儲存的bean類,TD為該bean的唯一標識的型別,一般為ObjectId。之後在service中注入該介面就可以使用,無需實現裡面的方法,spring會根據定義的規則自動生成。
例:
1 |
public interface PersonRepository extends |
3 |
MongoRepository<Person,
ObjectId>{ |
但是MongoRepository實現了的只是最基本的增刪改查的功能,要想增加額外的查詢方法,可以按照以下規則定義介面的方法。自定義查詢方法,格式為“findBy+欄位名+方法字尾”,方法傳進的引數即欄位的值,此外還支援分頁查詢,通過傳進一個Pageable物件,返回Page集合。
例:
1 |
public interface PersonRepository extends |
3 |
MongoRepository<Person,
ObjectId>{ |
5 |
public Page<Product>
findByAgeGreaterThan( int age,Pageable
page) ; |
下面是支援的查詢型別,每三條資料分別對應:(方法字尾,方法例子,mongodb原生查詢語句)
GreaterThan(大於)
findByAgeGreaterThan(int age)
{"age" : {"$gt" : age}}
LessThan(小於)
findByAgeLessThan(int age)
{"age" : {"$lt" : age}}
Between(在...之間)
findByAgeBetween(int from, int to)
{"age" : {"$gt" : from, "$lt" : to}}
IsNotNull, NotNull(是否非空)
findByFirstnameNotNull()
{"age" : {"$ne" : null}}
IsNull, Null(是否為空)
findByFirstnameNull()
{"age" : null}
Like(模糊查詢)
findByFirstnameLike(String name)
{"age" : age} ( age as regex)
(No keyword) findByFirstname(String name)
{"age" : name}
Not(不包含)
findByFirstnameNot(String name)
{"age" : {"$ne" : name}}
Near(查詢地理位置相近的)
findByLocationNear(Point point)
{"location" : {"$near" : [x,y]}}
Within(在地理位置範圍內的)
findByLocationWithin(Circle circle)
{"location" : {"$within" : {"$center" : [ [x, y], distance]}}}
Within(在地理位置範圍內的)
findByLocationWithin(Box box)
{"location" : {"$within" : {"$box" : [ [x1, y1], x2, y2]}}}
儘管以上查詢功能已經很豐富,但如果還不能滿足使用情況的話可以用一下方法---基於mongodb原本查詢語句的查詢方式。
例:在原介面中加入
1 |
@Query ( "{
'name':{'$regex':?2,'$options':'i'}, sales': {'$gte':?1,'$lte':?2}}" ) |
2 |
public Page<Product>
findByNameAndAgeRange(String name, double ageFrom, double ageTo,Pageable
page); |
註釋Query裡面的就是mongodb原來的查詢語法,我們可以定義傳進來的查詢引數,通過座標定義方法的引數。
還可以在後面指定要返回的資料欄位,如上面的例子修改如下,則只通過person表裡面的name和age欄位構建person物件。
1 |
@Query (value= "{
'name':{'$regex':?2,'$options':'i'}, sales':{'$gte':?1,'$lte':?2}}" ,fields= "{
'name' : 1, 'age' : 1}" ) |
2 |
public Page<Product>
findByNameAndAgeRange(String name, double ageFrom, double ageTo,Pageable
page); |