最近项目中有使用到Mongodb,通过学习相关API了解,Spring boot中提供了 `MongoTemplate`操作数据,可以实现大部分的业务场景,但每增加一个Collection业务对象就要增加对应的 `MongoTemplate`及对应的方法,例如分页这种通用的操作,基于提高代码复用效率(懒~)考虑,自己封装一个通用的Repository。
- 添加依赖,使用的Springboot 2.7.10
<!-- Mongodb 依赖 MongoTemplate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
- Mongodb基础配置,去除插入数据时保存的_class字段
@Configuration
public class MongoConfig {
@Resource
private MongoDatabaseFactory mongoDatabaseFactory;
@Resource
private MongoMappingContext mongoMappingContext;
@Bean
public MappingMongoConverter mappingMongoConverter() {
mongoMappingContext.setAutoIndexCreation(true);
mongoMappingContext.afterPropertiesSet();
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDatabaseFactory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
// 此处是去除插入数据库的 _class 字段
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
return converter;
}
}
- 定义IMongoRepository公共接口,使用@NoRepositoryBean表示不需要在初始时创建实例。
@NoRepositoryBean
public interface IMongoRepository<T, ID extends Serializable> extends MongoRepository<T,ID> {
/**
* 创建
*
* @param entity 新增内容
* @return 已创建的内容
*/
public T create(T entity);
/**
* 编辑
*
* @param id ID
* @param entity 编辑的内容
* @return 编辑后的内容
*/
public T update(ID id, T entity);
/**
* 删除
*
* @param ids 待删除的ID
* @return 删除的组件ID集合
*/
public List<ID> delete(Collection<ID> ids);
/**
* 根据ID查询
*
* @param id id
* @return 组件
*/
public T getOne(ID id);
/**
* 分页查询
*
* @param entity 查询条件
* @param pageRequest 分页信息
* @return 分页列表
*/
public Page<T> pageList(T entity, PageRequest pageRequest);
}
- 定义IMongoRepository的实现类
public class BaseMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements IMongoRepository<T, ID> {
protected final MongoOperations mongoOperations;
protected final MongoEntityInformation<T, ID> entityInformation;
public BaseMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
super(metadata, mongoOperations);
this.mongoOperations = mongoOperations;
this.entityInformation = metadata;
}
protected Class<T> getEntityClass() {
return entityInformation.getJavaType();
}
@Override
public T create(T entity) {
return this.save(entity);
}
@Override
public T update(ID id, T entity) {
T t1 = this.getOne(id);
BeanUtil.copyProperties(entity, t1, CopyOptions.create().ignoreNullValue());
return this.save(t1);
}
@Override
public List<ID> delete(Collection<ID> ids) {
ids.forEach(id -> {
T t = this.getOne(id);
this.delete(t);
});
return (List<ID>) ids;
}
@SneakyThrows
@Override
public T getOne(ID id) {
return this.findById(id)
.orElseThrow(() -> new Exception("未找到记录:" + id));
}
@Override
public Page<T> pageList(T entity, PageRequest pageRequest) {
return this.findAll(Example.of(entity), pageRequest);
}
}
- 在MongoConfig类上使用@EnableMongoRepositories将自定义的BaseMongoRepository替换原有SimpleMongoRepository
@EnableMongoRepositories(repositoryBaseClass = BaseMongoRepository.class, basePackages = {"com.learning.mongodb.crud.repository"})
@Configuration
public class MongoConfig {...}
- 验证
Book.java
@Document(collection = "Books")
@Data
public class Book {
@Id
private ObjectId id;
private String name;
private Double price;
}
BookRepository.java
public interface BookRepository extends IMongoRepository<Book, ObjectId> {
}
BookController.java
@Resource
private BookRepository bookRepository;
@PostMapping
public Book add(@RequestBody Book book) {
return this.bookRepository.save(book);
}
@GetMapping
public List<Book> books() {
return bookRepository.findAll();
}
@GetMapping(value = "/{id}")
public Book book(@PathVariable(name = "id") String id) {
return bookRepository.getOne(new ObjectId(id));
}
curl测试用例
添加书籍
curl --location 'http://localhost:8080/book' \
--header 'Content-Type: application/json' \
--data '{
"name":"C Primer Plus 第6版",
"price":53.9
}'
获取书籍
curl http://localhost:8080/book
总结
虽然Spring boot也提供了Mongodb JPA的操作类MongoRepository,但面对复杂操作时,没有MongoTemplate操作灵活,两个可以配合使用,取长补短。