赞
踩
spring data项目旨在对不同数据源提供一组相似的、较一致的具有spring style的交互方法。目的方便用户对不同数据源(关系数据库、非关系性数据等)的api操作,并简化系统持久层的代码逻辑结构。spring data项目包含多个子项目,不同数据源有不同的子项目对应。详见spring data官方文档 。
在项目开发过程中由于前期没有很好规划,mongoDB操作逻辑代码编码冗余重复;存在大量collection和属性名硬编码;mongoDB操作逻辑同业务逻辑混在一起,阅读困难;业务逻辑中存在大量复杂指标计算,业务逻辑复杂;这些导致系统后期需求开发缓慢,新人难以上手,维护难度大。基于此,本文想基于spring data的理念,浅谈一下面向mongoDB的数据持久层(dao层)设计,并给出设计示例以及spring data mongoDB的操作方法和使用步骤。
创建一个spring boot项目并实现对mongoDB的连接,具体可参见博文:Spring boot连接和操作mongoDB 。
本文基于yml配置。
1.在pom中引入相关包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
2.基于application.yml的连接配置
spring:
data:
mongodb:
database: 数据库名称
authentication-database: admin
uri: mongodb://用户名:密码@ip:端口号
在正确配置完yml后,spring容器启动后将自动实例化对mongoDB的连接,在service类中通过简单的@Autowire MongoTemplate即可编写操作mongoDB代码逻辑。本文希望通过Spring data的封装的公共方法,简化操作逻辑。org.springframework.data.repository.Repository接口及派生接口提供对部分mongoDB操作的封装。

@NoRepositoryBean注解避免了容器在启动时被作为一个bean实例创建。可以通过自定义接口继承MongoRepository使用这些方法。
如下截图展示了MongoRepository,PagingAndSortingRepository,CrudRepository封装的mongoDB公共操作方法,基本覆盖了mongoDB的常规操作。



Spring Data提供基于方法名称的统一操作范式,只需在接口层定义相应方法即可完成具体操作逻辑,** 这一点非常有利于面向Nosql的操作,可极大简化冗余代码操作逻辑。**我们知道在面向关系型数据库的持久层设计中,大名鼎鼎的mybatis框架以xml文件的方式避免了sql脚本对业务逻辑代码的侵入性,提供统一操作接口供sevice层调用。对于mongoDB需要掌握大量json操作命令的数据库交互方式来说。Spring Data基于接口方法名称的统一操作范式极大的降低了mongoDB的查询难度。
基于接口方法名称的统一操作典型范式如下:
interface PersonRepository extends Repository<User, Long> { List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // 通过lastname或firstname属性从Person表(@Document声明的对应mongoDB collection)查询记录并去重 List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // 通过lastname从Person表(@Document声明的对应mongoDB collection)查询记录忽略lastname大小写 List<Person> findByLastnameIgnoreCase(String lastname); // 通过lastname和firstname属性从Person表(@Document声明的对应mongoDB collection)查询记录忽略全部大小写 List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // 查询书结果并排序 List<Person> findByLastnameOrderByFirstnameAsc(String lastname); List<Person> findByLastnameOrderByFirstnameDesc(String lastname); }
也可在范式的基础上指定一些额外的规则
//查询结果后根据age倒序排序
@Query(sort = "{ age : -1 }")
List<Person> findByFirstname(String firstname);
@Query(sort = "{ age : -1 }")
List<Person> findByLastname(String lastname, Sort sort);
更多关于范式的查询请参见:Spring data官方文档
基于Spring Data封装的方法以及基于方法名称的范式,基本可覆盖80%的mongoDB常规操作。同学们可以根据需求进行定义接口。如果还有其他复杂查询,例如aggregaet,可以定义详细实现类作为扩展。
持久层(dao)结构如下:

代码示例如下:
T为实体类泛型,ID为实体类对应表的主键类型泛型。
BaseMongoDaoExtend提供复杂操作的封装,并对传参进行重载:
LatestDeviceInfoDaoExtend继承BaseMongoDaoExtend,完成一些具体操作实现,供service层调用。

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。