Spring Data MongoDB
按照 Spring 官网教程学习 Spring Data MongoDB。
核心概念
Spring Data repository 抽象中的核心接口是 org.springframework.data.repository.Repository
,作为一个标记接口,没有定义任何方法:
// Central repository marker interface
@Indexed
public interface Repository<T, ID> {
}
接口 org.springframework.data.repository.CrudRepository
定义了复杂的 CRUD 操作方法:
// Interface for generic CRUD operations on a repository for a specific type.
@NoRepositoryBean
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);
// 通过 ID 属性查询
Optional<T> findById(ID id);
Iterable<T> findAllById(Iterable<ID> ids);
boolean existsById(ID id);
// 返回所有记录
Iterable<T> findAll();
// 查询所有记录数
long count();
// 删除指定记录
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
// 删除所有记录
void deleteAll();
}
针对 MongoDB 提供了 org.springframework.data.mongodb.repository.MongoRepository
接口:
// Mongo specific Repository interface.
@NoRepositoryBean
public interface MongoRepository<T, ID>
extends ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
<S extends T> S insert(S entity);
<S extends T> List<S> insert(Iterable<S> entities);
@Override
<S extends T> List<S> findAll(Example<S> example);
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
org.springframework.data.repository.PagingAndSortingRepository
接口提供方法用于分页查询:
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends Repository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
使用方法
通过以下步骤使用 Spring Data MongoDB:
以查询 Person
为例
创建一个接口继承自
Repository
或者它的子接口,并指定泛型参数T
和ID
。public interface PersonRepository extends Repository<Person, ObjectId> { }
在接口中声明查询方法。
public interface PersonRepository extends Repository<Person, ObjectId> { List<Person> findByLastname(String lastname); }
通过注解
@EnableMongoRepositories
让 Spring 管理查询接口生成接口代理实现类。通过依赖注入获取接口实例,使用查询方法。
@SpringBootTest class PersonRepositoryTest { @Resource private PersonRepository personRepository; @Test void findByLastname() { var personList = personRepository.findByLastname("Matthews"); assertFalse(personList.isEmpty()); } }
定义 Repository
接口
定义 Repository 接口可以通过继承 Repository
及其子接口,也可以在自定义接口上增加 org.springframework.data.repository.RepositoryDefinition
注解:
// Annotating an interface with RepositoryDefinition will cause the same behaviour as extending Repository.
public @interface RepositoryDefinition {
Class<?> domainClass();
Class<?> idClass();
}
例如:
@RepositoryDefinition(domainClass = Person.class, idClass = ObjectId.class)
public interface AnnotationPersonRepository {
List<Person> findByLastname(String lastname);
}
微调 Repository 定义
如果只想暴露部分方法,比如自定义的 Repository 中不提供删除方法,可以从 CrudRepository
复制其它方法到接口中。
/**
* 自定义 Repository 只提供保存和查询方法
*
* @author linxiang
*/
@NoRepositoryBean
public interface CustomBaseRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID id);
}
增加 org.springframework.data.repository.NoRepositoryBean
注解避免 Spring 为接口创建代理对象。
使用多个 Spring Data 模块
可以在项目中同时使用多个 Spring Data 模块,比如 Spring Data Jpa 和 Spring Data MongoDB,有几种方式可以区分它们:
Repository 定义时继承特定接口,比如
MongoRepository
和JpaRepository
;通过实体类上的注解区分,比如
@Entity
用于 Jpa ,@Document
用于 MongoDB;通过
@Enable${store}Repositories
注解区分@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa") @EnableMongoRepositories(basePackages = "com.acme.repositories.mongo") class Configuration {}
MongoTemplate
介绍
org.springframework.data.mongodb.core.MongoTemplate
是 Spring MongoDB 的核心类,该模板提供了增删改查方法以及 MongoDB Document
和 Java POJO
转换的方法。MongoTemplate
是线程安全的。
MongoDB Document
和 Java pojo
转换是委托 org.springframework.data.mongodb.core.convert.MongoConverter
接口实现的,Spring 的默认实现类是 org.springframework.data.mongodb.core.convert.MappingMongoConverter
。
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo-template