Spring Data 是一个伞型项目,包含主流的数据库的访问技术。这些不同的数据访问项目都使用相同的编程模型,他们都是基于Repository规范接口。我们在本章选关系型数据库的访问技术Spring Data JPA和NoSQL的访问Spring Data Elasticsearch。
DDD是Domain-Driven Design的缩写,即领域驱动设计。它是解决复杂业务需求的一些列高级技术。
它的战术设计部分有几个重要概念和Spring Data有关系:
Set
一样保证数据的唯一性。我们先举例说明上面的概念:
public class Person {
private Long id;
private String name;
private Integer age;
private Address address;
private Collection<Child> children;
//...
}
Person
是实体类,因为设计小聚合的原则,Person
也是聚合与聚合根;
id
属性是唯一标识;
name
和age
是值,用来描述实体Person
;
同样address
和children
也是用来描述某个Person的,是对象形式的,所以它们是值对象。
Spring Data Repository对访问不同的数据库提供统一的抽象,它极大的减少了数据访问层的样板代码。Spring Data Repository抽象的核心是org.springframework.data.repository.Repository
,T
代表是它处理的实体的类型,ID代表实体的唯一标识。它的主要子接口有CrudRepository
定义新增、查询、更新、删除功能接口。PagingAndSortingRepository
又是CrudRepository
的子接口,定义了分页和排序的功能接口。
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity); //保存一个实体
<S extends T> Iterable<S> saveAll(Iterable<S> entities); //保存多个实体
Optional<T> findById(ID id); // 按照id查询实体
boolean existsById(ID id); // 按照id查询的实体是否存在
Iterable<T> findAll(); //查出所有实体
Iterable<T> findAllById(Iterable<ID> ids); //按照多个id查询多个实体
long count(); //计数实体
void deleteById(ID id); //按照id删除实体
void delete(T entity); //删除实体
void deleteAll(Iterable<? extends T> entities);//删除多个实体
void deleteAll(); //删除所有实体
}
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort); //根据排序参数查询出所有的实体
Page<T> findAll(Pageable pageable); //根据分野参数查询出所有的实体
}
针对不同的数据库,也有特定的子接口抽象,如:JpaRepository
、ElasticsearchRepository
等。
我们可以通过继承上面的接口来定义实体的Repository,并通过相关的开启配置(@EnableJpaRepositories
)的注解后,实体Repository会被Spring Data注册成为一个Bean,我们可以使用这个Bean进行数据访问操作了。
定义Repository:
public interface PersonRepository extends JpaRepository<Person, Long> {
}
使用Repository:
@RestController
@RequestMapping("/people")
public class PersonController {
private PersonRepository personRepository;
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping("/findByName")
public List<Person> findByName(@RequestParam String name){
return personRepository.findByName(name);
}
}
我们用相应注解将相应数据库的领域模型标识为实体,如:JPA使用的是@Entity
,Elasticsearch使用的是@Document
JPA:
@Entity
public class Person {
@Id
private Long id;
private String name;
private Integer age;
//...
}
Elasticsearch:
@Document(indexName = "person")
public class Person {}
Spring Data支持根据方法名中的属性进行推导查询,关键词可以是find...By
、read...By
、get…By
,By
之后是查询条件(where
之后的条件)
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> findByName(String name);
List<Person> findDistinctPersonByName(String name);
}
也可通过count...By
进行推导计数查询:
public interface PersonRepository extends JpaRepository<Person, Long> {
long countByName(String name);
}
也可通过delete...By
进行推导删除查询:
public interface PersonRepository extends JpaRepository<Person, Long> {
long deleteByName(String name);
List<Person> removeByName(String name);
}
By
之前还可以用通过firtst
、top
关键字来限制查询数量:
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> queryTop5ByName(String name);
List<Person> getFirst10ByName(String name);
}
关于更多Spring Data的查询关键字我们会在后续的详细讲解。
我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html
主要包含目录有:
第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和屁股里(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。