访问MongoDB数据(Accessing Data with MongoDB)

Spring Data

Spring Data的使命是为数据访问,提供一个熟悉的、一致的、基于Spring的编程模型;同时仍然保留底层数据存储的特殊特性。

它使使用数据访问(关系和非关系数据库、map-reduce框架和基于云的数据服务)技术变得容易。这是一个总括项目,其中包含许多特定于给定数据库的子项目。这些项目是,通过与许多支持这些令人兴奋的技术的公司和开发者合作开发的。

Spring Data MongoDB

Spring Data for MongoDB is part of the umbrella Spring Data project which aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities.

MongoDB的Spring Data是Spring Data总括项目的一部分,该项目旨在为新的数据存储,提供一个熟悉的、一致的、基于Spring的编程模型,同时保留特定于存储的特性和功能。

使用MongoDB访问数据

本指南引导你完成使用Spring Data MongoDB构建应用程序的过程,该应用程序将存储数据、检索数据,于MongoDB,一个基于文档的数据库。

你会建立什么

你将使用Spring Data MongoDB将Customer POJOs存储在MongoDB数据库中。

POJO

Plain Old Java Object。普通的旧Java对象

Plain Ordinary Java Object。简单的普通的Java对象

Plain 简单的;朴素的。 Ordinary 普通的。

环境依赖

在pom文件引入spring-boot-starter-data-mongodb依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

数据源配置

如果mongodb端口是默认端口,并且没有设置密码,可不配置,sprinboot会开启默认的。

spring.data.mongodb.uri: mongodb://localhost:27017/mongodbTest

mongodb设置了密码,这样配置:

spring.data.mongodb.uri: mongodb://name:pass@localhost:27017/mongodbTest

定义一个简单的实体

MongoDB是一个NoSQL文档存储。在这个例子中,你存储Customer对象。

package hello;

import org.springframework.data.annotation.Id;

public class Customer {

    @Id
    public String id;

    public String firstName;
    public String lastName;

    public Customer() {
    }

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format("Customer[id=%s, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }
}

这儿有一个Customer类,它有三个属性idfirstNamelastNameid主要被MongoDB的内部使用。在创建一个新实例时,你有一个构造函数来填充实体。

在本指南中,为了简洁,典型的getter和setter被省略了。

id符合MongoDB标识的标准名称,所以它不需要任何特殊的注释,来为Spring Data MongoDB标记它。

另外两个属性,firstNamelastName,没有注释。假设它们被映射到与属性本身同名的字段。

方便的toString()方法将打印出关于一个customer的细节。

MongoDB存储数据在集合中。Spring Data MongoDB把Customer类映射到一个名为customer的集合中。如果要更改集合的名称,可以在这个类上,使用Spring Data MongoDB的@Document注释。

创建简单的查询

Spring Data MongoDB专注于在MongoDB中存储数据。它还继承了Spring Data Commons项目的功能,例如派生查询的能力。从本质上说,您不必学习MongoDB的查询语言;您可以简单地编写一些方法,查询就被你写好了。

要查看这是如何工作的,请创建一个查询Customer文档的存储库接口

package hello;

import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.List;

public interface CustomerRepository extends MongoRepository<Customer, String> {

    Customer findByFirstName(String firstName);

    List<Customer> findByLastName(String lastName);
}

CustomerRepository扩展了MongoRepository接口,并插入了值和id的类型:CustomerString。开箱即用,这个接口有许多操作,包括标准的CRUD操作(create-read-update-delete)。

您可以通过简单地声明其方法签名来定义其他查询。在这种情况下,您添加findByFirstName,其实质上是寻找类型Customer的文档,并找到与firstName匹配的那一个。

findByLastName用过lastName,找到Customer的一个列表。

在典型的Java应用程序中,你写一个类来实现CustomerRepository和制作查询。使Spring Data MongoDB如此有用的原因是,您不必创建这个实现。当你运行程序时,Spring Data MongoDB在运行时创建它。

让我们把它连接起来,看看它是什么样的!

创建一个应用程序类

在这里你创建一个包含所有组件的应用程序类。

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private CustomerRepository repository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        repository.deleteAll();

        // save a couple of customers
        repository.save(new Customer("Alice", "Smith"));
        repository.save(new Customer("Bob", "Smith"));

        // fetch all customers
        System.out.println("Customer found with findByFirstName('Alice'):");
        System.out.println("-----------------------------------");
        System.out.println(repository.findByFirstName("Alice"));

        System.out.println("Customers found with findByLastName('Smith'):");
        System.out.println("-----------------------------------");
        for (Customer customer : repository.findByLastName("Smith")) {
            System.out.println(customer);
        }
    }
}

Spring Boot将自动处理这些存储库,只要它们被包含在你的@SpringBootApplication的相同包(或子包)中即可为了更好地控制注册过程,您可以使用@EnableMongoRepositories注释。

默认情况下,@EnableMongoRepositories将扫描当前软件包,以查找扩展了Spring Data存储库接口之一的任何接口。如果你的项目布局有多个项目,而且没有找到你的存储库,使用basePackageClasses=MyRepository.class安全地告诉Spring Data MongoDB按类型扫描不同的根包。

Spring Data MongoDB使用MongoTemplate来执行你的find*方法后面的查询。你可以自己使用该模板进行更复杂的查询,但是本指南并未包括此内容。

Application包括一个main()方法,该方法自动装入一个CustomerRepository实例:Spring Data MongoDB动态创建一个代理并将其注入给它(CustomerRepository)。

我们使用CustomerRepository通过一些测试。首先,它保存了一些Customer对象,演示了save()方法,并设置了一些将使用的数据。接下来,它调用findAll()来从数据库中获取所有Customer对象。然后,它调用findByFirstName()通过firstName获取一个Customer。最后,它调用findByLastName()来查找所有姓“Smith”的customers

Spring Boot默认尝试连接到本地托管的MongoDB实例。阅读参考文档,了解将应用程序指向其他地方的MongoDB实例的详细信息。

构建一个可执行的JAR

 

由于我们的Application实现了CommandLineRunner,当引导启动时,run方法被自动调用。

概要

恭喜!你编写了一个简单的应用程序,它使用Spring Data MongoDB来保存对象到数据库、从数据库中获取数据——所有这些都无需编写具体的存储库实现。

声明方法签名定义查询

findBy+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)

 

package hello;

import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.List;

public interface CustomerRepository extends MongoRepository<Customer, String> {

    Customer findByFirstName(String firstName);

    Customer findByAgeLessThan(int age);

    List<Customer> findByAgeLessThanEqual(int age);

    List<Customer> findByLastName(String lastName);

    /**
     * findBy+LastName+And+(Age+LessThan)
     * findBy+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)
     */
    List<Customer> findByLastNameAndAgeLessThan(String lastName, int age);

}

https://docs.spring.io/spring-data/mongodb/docs/2.0.3.RELEASE/reference/html/#repository-query-keywords

自定义Repository方法

Spring Data Repository包括标准的CRUD操作,声明方法签名定义查询。但某些场景下,你需要自定义。

我们来学习如何为单个Repository添加自定义方法

自定义Repository接口

首先我们需要添加一个自定义的接口,该接口定义了我们自定义的方法,这里我们自定义一个getLastName_AgeLt方法

package hello;

import java.util.List;

public interface CustomerRepositoryCustom {
    List<Customer> getLastName_AgeLt(String lastName, int age);
}

继承CustomerRepositoryCustom接口

然后,我们需要使CustomerRepository继承CustomerRepositoryCustom

package hello;

import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.List;

public interface CustomerRepository extends MongoRepository<Customer, String>, CustomerRepositoryCustom {

    Customer findByFirstName(String firstName);

    Customer findByAgeLessThan(int age);

    List<Customer> findByAgeLessThanEqual(int age);

    List<Customer> findByLastName(String lastName);

    /**
     * findBy+LastName+And+(Age+LessThan)
     * findBy+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)+And+property(+Logical keyword expressions)
     */
    List<Customer> findByLastNameAndAgeLessThan(String lastName, int age);
}

实现CustomerRepositoryCustom接口

既然是自定义的方法,就需要我们自己去实现该方法。由于我们需要为CustomerRepository添加自定义方法,Spring Data会自动的去寻找类名为CustomerRepositoryImpl的类作为自定义方法的实现(如果有两个以上类名为CustomerRepositoryImpl的类,Spring Data会抛出错误)。

注意:默认情况下,Spring Data 会在 base-package 中查找“接口名+Impl”作为实现类。也可以通过 repository-impl-postfix 声明后缀。

这个代码片段最有意思的地方在于实现类的名字遵循了命名规范,也就是Repository接口名字加上Impl后缀。

这个实现类如何被发现,并置于执行的代理之中呢?
实际上,Respository的启动过程看起来是这样子的。
1.发现Respository接口。(如CustomRepository)
2.寻找一个Bean定义,这个Bean的名字为接口名字加Impl后缀(如CumtomRepositoryImpl)。若找到,就使用它。
3.找到的自定义实现类将会自动装配到被发现接口的代理中。

实现类(CustomerRepositoryImpl)不需要注释@Repository

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.List;

public class CustomerRepositoryImpl implements CustomerRepositoryCustom {
    @Autowired
    MongoTemplate template;

    @Override
    public List<Customer> getLastName_AgeLt(String lastName, int age) {
        Query query = new Query(Criteria.where("lastName").is(lastName).and("age").lt(age));
        return template.find(query, Customer.class);
    }
}

 

 

使用REST访问MongoDB数据

RESTful:Representational State Transfer,表述性状态转移。面向资源的架构。

一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

  REST基础概念:

  • 在REST中的一切都被认为是一种资源。
  • 每个资源由URI标识。
  • 使用统一的接口。处理资源使用POST,GET,PUT,DELETE操作类似创建,读取,更新和删除(CRUD)操作。
  • 无状态。每个请求是一个独立的请求。从客户端到服务器的每个请求都必须包含所有必要的信息,以便于理解。
  • 通信都是通过展现。例如XML,JSON

资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。

对使用基于超媒体的RESTful前端,展示MongoDB存储库,如果你感兴趣,那么你可能想要阅读使用REST访问MongoDB数据

 

 

参考资料:Accessing Data with MongoDB

Accessing MongoDB Data with REST

SpringBoot非官方教程 | 第八篇:springboot整合mongodb - 方志朋的专栏 - CSDN博客

Spring Boot Reference Guide

Spring Data MongoDB - Reference Documentation#9.6. Querying Documents

Spring Data JPA: 为单个Repository添加自定义方法

Spring Data中手动实现Repository方法

源码:https://gitee.com/SevenDayBabyface/demo

源码:https://gitee.com/SevenDayBabyface/demo

posted @ 2018-01-22 15:05  己为  阅读(275)  评论(0编辑  收藏  举报