SpringData的官方文档Spring Data MongoDB - Reference Documentation,阅读官方文档永远是最好的学习方法.
MongoTemplate
的使用示例创建SpringBoot项目,在pom.xml
中添加依赖如下:
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-mongodbartifactId>
dependency>
在cn.maoritian.domain
包下创建实体类Preson
如下:
package cn.maoritian.domain;
public class Person {
private String id;
private String name;
private int age;
public String getId() {return id; }
public String getName() {return name; }
public int getAge() {return age; }
public Person(String name, int age) {this.name = name; this.age = age; }
@Override
public String toString() {return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; }
}
在cn.maoritian
包下创建SpringBoot启动类MongoApp
,在其main()
函数中进行对MongoDB的操作
package cn.maoritian;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import cn.maoritian.domain.Person;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import com.mongodb.MongoClient;
public class MongoApp {
private static final Log log = LogFactory.getLog(MongoApp.class);
public static void main(String[] args) throws Exception {
MongoOperations mongoOps = new MongoTemplate(new MongoClient(), "数据库名");
mongoOps.insert(new Person("Joe", 34)); // 默认插入进名为person的collection
log.info(mongoOps.findOne(new Query(where("name").is("Joe")), Person.class));
mongoOps.dropCollection("person");
}
}
程序输出如下:
22:35:59.212 [main] DEBUG org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator - Analyzing class class cn.maoritian.domain.Person for index information.
22:35:59.260 [main] DEBUG org.springframework.data.mongodb.core.MongoTemplate - Inserting Document containing fields: [name, age, _class] in collection: person
22:35:59.337 [main] DEBUG org.springframework.data.mongodb.core.MongoTemplate - findOne using query: { "name" : "Joe" } fields: Document{{}} for class: class cn.maoritian.domain.Person in collection: person
22:35:59.372 [main] INFO cn.maoritian.MongoApp - Person [id=5d7e4c39676d91262cdf734f, name=Joe, age=34]
22:35:59.384 [main] DEBUG framework.data.mongodb.core.MongoTemplate: 375 - Dropped collection [database.person]
MongoTemplate
的使用MongoTemplate
下面三种方式均可向Spring容器中注入MongoTemplate
:
使用.xml
文件注入:
<mongo:mongo-client host="localhost" port="27017"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoClient"/>
<constructor-arg name="databaseName" value="数据库名"/>
bean>
使用Java Config注入:
@Configuration
public class AppConfig {
public @Bean MongoClient mongoClient() {
return new MongoClient("localhost");
}
public @Bean MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), "数据库名");
}
}
在SpringBoot项目中,还可以使用.yml
文件注入
spring:
data:
mongodb:
uri: mongodb://服务器IP地址:端口号/数据库名
其中,mongodb属性对应的所有yml配置项均为org.springframework.boot.autoconfigure.mongo.MongoProperties
类的属性,其源代码如下:
package org.springframework.boot.autoconfigure.mongo;
import com.mongodb.MongoClientURI;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.data.mongodb") // 指明yml配置的前缀
public class MongoProperties {
public static final int DEFAULT_PORT = 27017;
public static final String DEFAULT_URI = "mongodb://localhost/test";
private String host;
private Integer port = null;
private String uri;
private String database;
private String authenticationDatabase;
private String gridFsDatabase;
private String username;
private char[] password;
private Class<?> fieldNamingStrategy;
// get,set方法...
}
_id
字段映射MongoDB要求每个文档包含一个_id
字段,在实体类中,如下两种属性会被映射为_id
字段:
@Id
注解的属性会被映射为数据库_id
字段.id
的属性会被映射为数据库_id
字段._class
字段映射当一个POJO对象被转换为MongoDB中的文档时,会自动在文档末尾加入一个_class
字段,其值为该POJO类的全限定类名(fully qualified classname
).
下面例子展示一个实体类与其转化为的MongoDB文档间的关系:
public class Sample {
Contact value;
}
public abstract class Contact { … }
public class Person extends Contact { … }
Sample sample = new Sample();
sample.value = new Person();
mongoTemplate.save(sample);
{
"value" : { "_class" : "cn.maoritian.Person" },
"_class" : "cn.maoritian.Sample"
}
如果不想在_class
字段中保存整个类名,可以在POJO类上使用@TypeAlias
注解,其值为_class
字段的值.
@TypeAlias("pers")
class Person {
...
}
{
"value" : { "_class" : "pers" },
"_class" : "cn.maoritian.Sample"
}
通过向Spring容器中注入MongoTypeMapper
的实现类,我们可以配置自定义类型映射.
class CustomMongoTypeMapper extends DefaultMongoTypeMapper {
//implement custom type mapping here
}
@Configuration
class SampleMongoConfiguration extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "数据库名";
}
@Override
public MongoClient mongoClient() {
return new MongoClient();
}
@Bean
@Override
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter mmc = super.mappingMongoConverter();
mmc.setTypeMapper(customTypeMapper());
return mmc;
}
@Bean
public MongoTypeMapper customTypeMapper() {
return new CustomMongoTypeMapper();
}
}
MongoTemplate
进行CRUD对于每个实体类,MongoTemplate
会将其对象存入一个单独的集合(collection
)中,该集合的默认集合名为实体类名首字母变小写(如cn.maoritian.Person
类的所有实例默认会被存入person
集合中).
可以在实体类上加以@Document
注解,其collection
属性指定将该类的实例对象存入的集合名.
@Document(collection = "集合名")
public class Person {
// ...
}
insert
/save
)文档的方法下面三个方法可以向MongoDB中保存文档
insert(Object objectToSave)
和insert(Object objectToSave, String collectionName)
: 将objectToSave
存入MongoDB中,若与集合中现有文档发生_id
字段冲突,则报错.insertAll(Collection
: 将集合objectsToSave
中的所有对象存入MongoDB中,若与集合中现有文档发生_id
字段冲突,则报错.save(Object objectToSave)
和save(Object objectToSave, String collectionName)
: 将objectToSave
存入MongoDB中,若与集合中现有文档发生_id
字段冲突,则覆盖之前的文档.query
)文档的方法下面五个方法可以查询MongoDB中的文档
List findAll(Class entityClass)
和 List findAll(Class entityClass, String collectionName)
: 查询所有T类型的文档. T findOne(Query query, Class entityClass)
和T findOne(Query query, Class entityClass, String collectionName)
: 查询一个满足query
条件的文档. T findById(Object id, Class entityClass)
和 T findById(Object id, Class entityClass, String collectionName)
: 通过id
查询文档. List find(Query query, Class entityClass)
和 List find(Query query, Class entityClass, String collectionName)
: 查询所有满足query
条件的文档.List<Person> result = mongoTemplate.find(query(where("age").lt(50)
.and("accounts.balance").gt(1000.00d)), Person.class);
通过Query.addCriteria()
方法,我们可以使用Criteria
对象构造Query
对象.Criteria
的方法与MongoDB的操作符一一对应如下:
Criteria 的方法 |
对应的MongoDB操作符 |
---|---|
Criteria all(Object o) |
$all |
Criteria and(String key) |
对key 增加链式Criteria |
Criteria andOperator(Criteria… criteria) |
$and |
Criteria elemMatch(Criteria c) |
$elemMatch |
Criteria exists(boolean b) |
$exists |
Criteria gt(Object o) |
$gt |
Criteria gte(Object o) |
$gte |
Criteria in(Object… o) |
$in |
Criteria in(Collection> collection) |
$in |
Criteria is(Object o) |
field matching({ key:value } ).顺序敏感(field sensitive ) |
Criteria lt(Object o) |
$lt |
Criteria lte(Object o) |
$lte |
Criteria mod(Number value, Number remainder) |
$mod |
Criteria ne(Object o) |
$ne |
Criteria nin(Object… o) |
$nin |
Criteria norOperator(Criteria… criteria) |
$nor |
Criteria not() |
$not |
Criteria orOperator(Criteria… criteria) |
$or |
Criteria regex(String re) |
$regex |
Criteria size(int s) |
$size |
Criteria type(int t) |
$type |
update
)文档的方法下面两个方法可以修改MongoDB中的文档
updateFirst(Query query, Update update, Class> entityClass)
和updateFirst(Query query, Update update, String collectionName)
: 修改第一个满足条件的文档.updateMulti(Query query, Update update, Class> entityClass)
和updateMulti(Query query, Update update, String collectionName)
: 修改第一个满足条件的文档.参数的意义如下:
query
: 表示查询条件update
: 表示修改操作import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query;
import static org.springframework.data.mongodb.core.query.Update;
WriteResult wr = mongoTemplate.updateMulti(new Query(where("accounts.accountType").is(Account.Type.SAVINGS)),
new Update().inc("accounts.$.balance", 50.00), Account.class);
Update
对象可以通过链式调用添加修改操作.常见的方法如下,与MongoDB的修改操作符有一一对应的关系
Update 的实例方法 |
对应的MongoDB操作符 |
---|---|
Update addToSet(String key, Object value) |
$addToSet |
Update currentDate(String key) |
$currentDate |
Update currentTimestamp(String key) |
$currentDate |
Update inc(String key, Number inc) |
$inc |
Update max(String key, Object max) |
$max |
Update min(String key, Object min) |
$min |
Update multiply(String key, Number multiplier) |
$mul |
Update pop(String key, Update.Position pos) |
$pop |
Update pull(String key, Object value) |
$pull |
Update pullAll(String key, Object[] values) |
$pullAll |
Update push(String key, Object value) |
$push |
Update pushAll(String key, Object[] values) |
$pushAll |
Update rename(String oldName, String newName) |
$rename |
Update set(String key, Object value) |
$set |
Update setOnInsert(String key, Object value) |
$setOnInsert |
Update unset(String key) |
$unset |
下面四个例子展示了Update
对象和MongoDB操作符的对应关系:
new Update().push("category").each("spring", "data")
new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel"));
new Update().push("key").slice(5).each(Arrays.asList("Arya", "Arry", "Weasel"));
new Update().addToSet("values").each("spring", "data", "mongodb");
{ $push : { "category" : { "$each" : [ "spring" , "data" ] } } }
{ $push : { "key" : { "$position" : 0 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } }
{ $push : { "key" : { "$slice" : 5 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } }
{ $addToSet : { "values" : { "$each" : [ "spring" , "data" , "mongodb" ] } } }
upsert
)文档的方法更新插入upsert(Query query, Update update, Class> entityClass)
和upsert(Query query, Update update, String collectionName)
方法,执行的是保存或修改过程.
query
条件能查到文档,则执行updateFirst()
操作query
条件不能查到文档,则执行insert()
操作mongoTemplate.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")),
update("address", addr), Person.class);
find and modify
)文档的方法查询并修改find and modify
有如下四个重载方法:
T findAndModify(Query query, Update update, Class entityClass);
T findAndModify(Query query, Update update, Class entityClass, String collectionName);
T findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass);
T findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass, String collectionName);
其中options
参数封装了修改操作的一些选项如下:
returnNew
属性取值true|false
,默认值为false
.表示返回的是修改前的查询结果还是修改后的结果upsert
属性取值true|false
,默认值为false
.取值为true
表示执行upsert
操作;取值为false
表示执行update
操作.remove
属性取值true|false
,默认值为false
.表示是否删除掉查询结果mongoTemplate.insert(new Person("Harry", 23));
Query query1 = new Query(Criteria.where("firstName").is("Harry"));
Update update1 = new Update().inc("age", 1);
Person p1 = mongoTemplate.findAndModify(query1, update1, Person.class);
// 得到 Person [id=5d90533e74fa159cdb13cae0, firstName=Harry, age=1]
Query query2 = new Query(Criteria.where("firstName").is("Mary"));
Update update2 = new Update().inc("age", 1);
Person p2 = mongoTemplate.findAndModify(query2, update2, new FindAndModifyOptions().returnNew(true).upsert(true), Person.class);
// 得到 Person [id=5d9054b574fa159cdb13cae1, firstName=Mary, age=1]
find and remove
)文档的方法查询并删除文档的方法findAndRemove()
与findAndModify()
的使用几乎完全相同,有以下几个重载的方法:
List findAllAndRemove(Query query, String collectionName)
List findAllAndRemove(Query query, Class entityClass)
List findAllAndRemove(Query query, Class entityClass, String collectionName)
find and replace
)文档的方法与findAndModify()
方法类似,findAndReplace()
方法也需要指定一个option
Optional<User> result = template.update(Person.class)
.matching(query(where("firstame").is("Tom")))
.replaceWith(new Person("Dick"))
.withOptions(FindAndReplaceOptions.options().upsert())
.as(User.class)
.findAndReplace();