< dependency >
< groupId > org.springframework.data </ groupId >
< artifactId > spring - data - mongodb </ artifactId >
< version > 1.0 . 0 .M5 </ version >
</ dependency >
< beans xmlns = " http://www.springframework.org/schema/beans "
xmlns:xsi = " http://www.w3.org/2001/XMLSchema-instance " xmlns:context = " http://www.springframework.org/schema/context "
xmlns:mongo = " http://www.springframework.org/schema/data/mongo "
xsi:schemaLocation = " http://www.springframework.org/schema/context
http: // www.springframework.org/schema/context/spring-context-3.0.xsd
http: // www.springframework.org/schema/data/mongo
http: // www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http: // www.springframework.org/schema/beans
http: // www.springframework.org/schema/beans/spring-beans-3.0.xsd">
< context:property - placeholder location = " classpath*:META-INF/mongodb/mongodb.properties " />
<!-- 定义mongo对象,对应的是mongodb官方jar包中的Mongo,replica - set设置集群副本的ip地址和端口 -->
< mongo:mongo id = " mongo " replica - set = " localhost:27017 " >
<!-- 一些连接属性的设置 -->
< mongo:options
connections - per - host = " ${mongo.connectionsPerHost} "
threads - allowed - to - block - for - connection - multiplier = " ${mongo.threadsAllowedToBlockForConnectionMultiplier} "
connect - timeout = " ${mongo.connectTimeout} "
max - wait - time = " ${mongo.maxWaitTime} "
auto - connect - retry = " ${mongo.autoConnectRetry} "
socket - keep - alive = " ${mongo.socketKeepAlive} "
socket - timeout = " ${mongo.socketTimeout} "
slave - ok = " ${mongo.slaveOk} "
write - number = " 1 "
write - timeout = " 0 "
write - fsync = " true " />
</ mongo:mongo >
<!-- mongo的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 -->
< mongo:db - factory dbname = " test " mongo - ref = " mongo " />
<!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 -->
< bean id = " mongoTemplate " class = " org.springframework.data.mongodb.core.MongoTemplate " >
< constructor - arg name = " mongoDbFactory " ref = " mongoDbFactory " />
</ bean >
<!-- 映射转换器,扫描back - package目录下的文件,根据注释,把它们作为mongodb的一个collection的映射 -->
< mongo:mapping - converter base - package = " com.xxx.xxx.domain " />
<!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 -->
< mongo:repositories base - package = " com.xxx.xxx.persist.mongodb " />
<!-- To translate any MongoExceptions thrown in @Repository annotated classes -->
< context:annotation - config />
</ 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类
@CompoundIndexes({
@CompoundIndex(name = " age_idx " , def = " {'lastName': 1, 'age': -1} " )
})
public class Person < T extends Address > {
@Id
private String id;
@Indexed(unique = true )
private Integer ssn;
private String firstName;
@Indexed
private String lastName;
private Integer age;
@Transient
private Integer accountTotal;
@DBRef
private List < Account > accounts;
private T address;
public Person(Integer ssn) {
this .ssn = ssn;
}
@PersistenceConstructor
public Person(Integer ssn, String firstName, String lastName, Integer age, T address) {
this .ssn = ssn;
this .firstName = firstName;
this .lastName = lastName;
this .age = age;
this .address = address;
}
public class Account {
@Id
private ObjectId id;
private Float total;
}
与HibernateRepository类似,通过继承MongoRepository接口,我们可以非常方便地实现对一个对象的增删改查,要使 用Repository的功能,先继承MongoRepository<T, TD>接口,其中T为仓库保存的bean类,TD为该bean的唯一标识的类型,一般为ObjectId。之后在service中注入该接口就可以 使用,无需实现里面的方法,spring会根据定义的规则自动生成。
例:
MongoRepository < Person, ObjectId > {
// 这里可以添加额外的查询方法
}
例:
MongoRepository < Person, ObjectId > {
// 查询大于age的数据
public Page < Product > findByAgeGreaterThan( int age,Pageable page) ;
}
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原本查询语句的查询方式。
例:在原接口中加入
public Page < Product > findByNameAndAgeRange(String name, double ageFrom, double ageTo,Pageable page);
注释Query里面的就是mongodb原来的查询语法,我们可以定义传进来的查询参数,通过坐标定义方法的参数。
还可以在后面指定要返回的数据字段,如上面的例子修改如下,则只通过person表里面的name和age字段构建person对象。
public Page < Product > findByNameAndAgeRange(String name, double ageFrom, double ageTo,Pageable page);