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类,它有三个属性id,firstName和lastName。id主要被MongoDB的内部使用。在创建一个新实例时,你有一个构造函数来填充实体。
在本指南中,为了简洁,典型的getter和setter被省略了。
id符合MongoDB标识的标准名称,所以它不需要任何特殊的注释,来为Spring Data MongoDB标记它。
另外两个属性,firstName和lastName,没有注释。假设它们被映射到与属性本身同名的字段。
方便的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的类型:Customer和String。开箱即用,这个接口有许多操作,包括标准的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); }
自定义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 Data MongoDB - Reference Documentation#9.6. Querying Documents
Spring Data JPA: 为单个Repository添加自定义方法
源码:https://gitee.com/SevenDayBabyface/demo