spring 於mongodb整合

edagarli發表於2014-03-26
這裡我們用到的是spring-data中一個整合mongodb的專案,首先在maven中新增對它的依賴,這裡我用的是1.0.0.M5版本
1 <!-- mongodb spring --> 
2 <dependency
3     <groupId>org.springframework.data</groupId
4     <artifactId>spring-data-mongodb</artifactId
5     <version>1.0.0.M5</version
6 </dependency>

然後是配置檔案

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-placeholderlocation="classpath*:META-INF/mongodb/mongodb.properties"/>
12      
13     <!-- 定義mongo物件,對應的是mongodb官方jar包中的Mongo,replica-set設定叢集副本的ip地址和埠 -->
14     <mongo:mongo id="mongo" replica-set="localhost:27017">
15         <!-- 一些連線屬性的設定 -->   
16         <mongo:options
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}"
25              write-number="1"
26              write-timeout="0"
27              write-fsync="true"/>       
28     </mongo:mongo>
29  
30     <!-- mongo的工廠,通過它來取得mongo例項,dbname為mongodb的資料庫名,沒有的話會自動建立 -->
31     <mongo:db-factory dbname="test" mongo-ref="mongo"/>
32  
33     <!-- mongodb的主要操作物件,所有對mongodb的增刪改查的操作都是通過它完成 -->
34     <bean id="mongoTemplate"class="org.springframework.data.mongodb.core.MongoTemplate">
35       <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
36     </bean>
37      
38     <!-- 對映轉換器,掃描back-package目錄下的檔案,根據註釋,把它們作為mongodb的一個collection的對映 -->
39     <mongo:mapping-converter base-package="com.xxx.xxx.domain" />
40      
41     <!-- mongodb bean的倉庫目錄,會自動掃描擴充套件了MongoRepository介面的介面進行注入 -->
42     <mongo:repositories base-package="com.xxx.xxx.persist.mongodb"/>
43  
44     <!-- To translate any MongoExceptions thrown in @Repository annotated classes -->
45     <context:annotation-config />
46      
47 </beans>
這樣基本配置就完成了


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")
02 @CompoundIndexes({
03     @CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
04 })
05 public class Person<T extends Address> {
06  
07   @Id
08   private String id;
09   @Indexed(unique = true)
10   private Integer ssn;
11   private String firstName;
12   @Indexed
13   private String lastName;
14   private Integer age;
15   @Transient
16   private Integer accountTotal;
17   @DBRef
18   private List<Account> accounts;
19   private T address;
20  
21    
22   public Person(Integer ssn) {
23     this.ssn = ssn;
24   }
25    
26   @PersistenceConstructor
27   publicPerson(Integer ssn, String firstName, String lastName, Integer age, T address) {
28     this.ssn = ssn;
29     this.firstName = firstName;
30     this.lastName = lastName;
31     this.age = age;
32     this.address = address;
33   }
Account類
1 @Document
2 public class Account {
3  
4   @Id
5   private ObjectId id;
6   private Float total;
7  
8 }

與HibernateRepository類似,通過繼承MongoRepository介面,我們可以非常方便地實現對一個物件的增刪改查,要使用Repository的功能,先繼承MongoRepository<T, TD>介面,其中T為倉庫儲存的bean類,TD為該bean的唯一標識的型別,一般為ObjectId。之後在service中注入該介面就可以使用,無需實現裡面的方法,spring會根據定義的規則自動生成。

例:

1 public interface PersonRepository extends
2  
3 MongoRepository<Person, ObjectId>{
4 //這裡可以新增額外的查詢方法
5
但是MongoRepository實現了的只是最基本的增刪改查的功能,要想增加額外的查詢方法,可以按照以下規則定義介面的方法。自定義查詢方法,格式為“findBy+欄位名+方法字尾”,方法傳進的引數即欄位的值,此外還支援分頁查詢,通過傳進一個Pageable物件,返回Page集合。

例:

1 public interface PersonRepository extends
2  
3 MongoRepository<Person, ObjectId>{
4  //查詢大於age的資料
5        public Page<Product> findByAgeGreaterThan(int age,Pageable page) ;
6
下面是支援的查詢型別,每三條資料分別對應:(方法字尾,方法例子,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,doubleageTo,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,doubleageTo,Pageable page);

相關文章