译:Spring Data MongoDB 简介 | Spring For All

282 阅读8分钟
原文链接: www.spring4all.com

Spring Data MongoDB 简介

原文链接:www.baeldung.com/spring-data…

作者:baeldung

译者:wjtBrid

1.概述

本文将通过 MongoTemplate 和 MongoRepository 演示一些基本增删改查的操作。快速实用的 介绍 Spring Data MongoDB

2.MongoTmplate 和 MongoRepository

MongoTemplate 遵循 Spring 中的标准模板模式,并为底层持久性引擎提供了随时可用的基本 API。

repository 遵循以 Spring Data 为中心的方法,并基于所有 Spring Data 项目中众所周知的访问模式,提供更灵活,更复杂的API操作。

对于以上,我们首先需要定义依赖 - 例如,在 maven 的 pom.xml 中添加:

<dependency><groupId>org.springframework.data</groupId>
   <artifactId>spring-data-mongodb</artifactId>
   <version>1.10.4.RELEASE</version>
</dependency>

请检查是否有新的版本发布-版本记录

3.MongoTemplate 配置

3.1 XML 配置

让我们为 MongTemplate 做一个简单的XML配置:

<mongo:mongo id="mongo" host="localhost" /> 
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-ref="mongo" />

首先,我们需要定义一个 factory bean 用来创建 Mongo 实例。
接下来,我们需要定义(配置)template bean:

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
    <constructor-arg ref="mongoDbFactory"/> 
</bean>

最后我们需要定义一个 post processor 用来处理任何在 @Repository 注解类中抛出的 MongoException 异常:

<bean class=  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

3.2 Java 配置

现在让我们通过扩展 MongoDB 配置的基类 AbstractMongoConfiguration,使用 Java 新建一个类似的配置:

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public Mongo mongo() throws Exception {
        return new MongoClient("127.0.0.1", 27017);
    }

    @Override
    protected String getMappingBasePackage() {
        return "org.baeldung";
    }
}

注意:我们不需要再定义 MongoTemplate bean,因为它已在 AbstractMongoConfiguration 中定义,我们也可以使用不扩展 AbstractMongoConfiguration 的自定义的配置 - 如下所示:

@Configuration
public class SimpleMongoConfig {

    @Bean
    public Mongo mongo() throws Exception {
        return new MongoClient("localhost");
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4.MongoRepository 配置

4.1 XML 配置

要使用自定义 repositories(扩展自 MongoRepository) - 我们需要继续使用3.1节中的配置并设置 repositories:

<mongo:repositories
  base-package="org.baeldung.repository" mongo-template-ref="mongoTemplate"/>

4.2 Java 配置

在3.2节中创建的配置的基础上,新添加一个注解:

@EnableMongoRepositories(basePackages = "org.baeldung.repository")

4.3 创建 Repository

完成以上配置之后,我们需要创建一个继承自 MongoRepository 接口的 repository 接口:

public interface UserRepository extends MongoRepository<User, String> {
    // 
}

现在我们可以自动注入这个 UserRepository 使用 MongoRepository 已定义的操作或者新增一些自定义操作。

5.使用 MongoTemplate

5.1 Insert

让我们开始使用 Insert 操作;使用一个空的 database:

{
}

现在,如果我们 Insert 一个新的 user:

User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");

database 将会看到如下:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jon"
}

5.2 Save - Insert

这个 save 操作是一个 sava-or-update 的语义:如果一个 id 已经存在,它会的语义为更新,如果不存在它的语义为新增。

参考第一个 insert 的语义;初始化 database 状态:

{
}

当我们 save 一个新的 user:

User user = new User();
user.setName("Albert"); 
mongoTemplate.save(user, "user");

这个数据将会被新增到 database:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Albert"
}

下一小节,我们将会看到使用相同的操作 save 所展示的更新语义。

5.3 Save-Update

现在让我使用 save 的更新语义,操作一个已存在的数据:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jack"
}

当我 save 一个已经存在的 user,我们将会更新它:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");

database 将会看到如下:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jim"
}

如你所见,在这个例子中,因为我们使用了一个已存在的 _id 的数据,所以 save 操作展示了 update 的语义。

5.4 UpdateFirst

updateFirst 更新查询匹配的第一个 document。

首先,初始化 database 的状态:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alex"
    }
]

运行 updateFirst:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);

只有第一条记录被更新了:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "James"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alex"
    }
]

5.5 UpdateMulti

UpdateMulti 更新所有匹配的 document

首先,以下为在 updateMulti 之前的 database 状态:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eugen"
    }
]

运行 updateMulti:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);

所有在 database 中的数据将会被更新:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Victor"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.baeldung.model.User",
        "name" : "Victor"
    }
]

5.6 FindAndModify

这个操作类似于 updateMulti,但是它返回了对象被修改之前的数据

首先,在做 findAndModify 之前的 database 状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Markus"
}

观察实际操作的代码:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);

返回的数据对象将会和在 database 中初始的数据一样。
然而在 database 中新的数据状态为:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Nick"
}

5.7 Upsert

upsert 意为查询、修改同时创建:如果 document 匹配则更新它,否则通过组合查询和更新对象来创建新 document。

首先,初始化 database 的状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Markus"
}

开始运行 upsert:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);

运行后 database 的状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Nick"
}

5.8 Remove

运行 remove 之前的 database 状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Benn"
}

开始运行 remove:

mongoTemplate.remove(user, "user");

所期望的结果:

{
}

6.使用 MongoRepository

6.1 Insert

运行 insert 之前的 database 状态:

{
}

当 insert 一个新的 user:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

运行后的 database 状态:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jon"
}

注意该操作与 MongoTemplate API 中的插入操作的工作方式相同。

6.2 Save - Insert

类似 - save 的工作方式与 MongoTemplate API 中的 save 操作相同。

让我们从操作新增语义开始;这是数据库的初始状态:

{
}

我们执行相同的操作:

User user = new User();
user.setName("Aaron");
userRepository.save(user);

数据将会被新增到 database 中:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Aaron"
}

注意,在这个例子中,save 为新增语义,是因为我们插入了一个新的对象。

6.3 Save - Update

现在让我们看一下相同的操作但是为更新语义

在运行新的 save 的 database 状态:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jack"81*6
}

执行相同的操作:

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);

database 的最终状态:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.baeldung.model.User",
    "name" : "Jim"
}

注意,在这个例子中,save 为更新语义,因为我们使用了一个已经存在的对象。

6.4 Delete

运行 delete 之前的 database 状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Benn"
}

运行 delete:

userRepository.delete(user);

结果将类似为:

{
}

6.5 FindOne

运行 findOne 时的 database 状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Chris"
}

运行 findOne:

userRepository.findOne(user.getId())

结果将会返回已经存在的数据:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Chris"
}

6.6 Exists

运行 exists 之前的 database 状态:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Harris"
}

运行 exists:

boolean isExists = userRepository.exists(user.getId());

结果返回 true。

6.7 FindAll 并排序

运行 findAll 之前的 database 状态:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Brendan"
    },
    {
       "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
       "_class" : "org.baeldung.model.User",
       "name" : "Adam"
    }
]

运行 findAll with Sort:

List<User> users = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));

结果将为以 name 为升序进行排列:

[
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Adam"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Brendan"
    }
]

6.8 FindAll 并分页

运行 findAll 之前的 database 状态:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.baeldung.model.User",
        "name" : "Adam"
    }
]

运行一个带有分页请求的 findAll:

Pageable pageableRequest = new PageRequest(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();

结果为在 user list 中只含有一个 user:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.baeldung.model.User",
    "name" : "Brendan"
}

7.注解

最后,让我们回顾一下 Spring Data 使得这些 API 生效的简单注解。

@Id
private String id;

field 级别的@Id 注解可以声明在任何类型上,包括 long 和 String。

如果@Id字段的值不为 null,则按原样存储在数据库中;否则,转换器将假定您要在数据库中存储 ObjectId(ObjectId,String或BigInteger)。

@Document:

@Document
public class User {
    //
}

此注解仅将类标记为需要持久保存到数据库的域对象,同时允许我们选择要使用的集合的名称。

8.总结

本文是一个 MongoDB 结合 Spring Data 快速而全面的使用介绍,既可以使用 MongoTemplate API,也可以使用 MongoRepository。
所有以上示例和代码片段的实现都可以在Github上找到 - 这是一个基于Maven的项目,所以它可以很容易导入、运行。

关注社区公号,加入社区纯技术微信群