SpringBoot操作MongoDB之MongoRepository

3 篇文章 0 订阅
2 篇文章 0 订阅

前言

之前写过一篇关于MongoDB的总结

其中就已经包含了SpringBoot操作MongoDB之MongoRepository了

但是因为觉得单单与Springboot内容就比较多,而且开发时还会进行多次补充总结,

觉得独立出来一篇是非常必要的,所以就有这篇的出现。

参考链接

NoSQL_MongoDB
Spring data Mongodb Query以分页

时间线

20200825-完成初稿

MongoRepository简介

关于springboot操作mongodb,使用spring-data其实有两种方式:MongoRepository 和 MongoTemplate

但是日常使用中,与MongoRepository相比,MongoTemplate需要进行相关配置,而MongoRepository能够满足一般的需求开发,而且拿来即用即可。非常方便

使用前的准备

Maven

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

application.properties配置

#### 链接数据库
# 备注:user=root,password=123456,host=192.168.1.100,port=27017,db=admin
# url配置方式,如果有设置密码的话,这种方式非常简洁
# 但找不到资料,当没有设置密码时,如何处理
spring.data.mongodb.uri=mongodb://root:123456@192.168.1.100:27017/admin
# 逐一配置,适合未设置密码的MongoDB
spring.data.mongodb.database=test
spring.data.mongodb.host=host
spring.data.mongodb.port=27017
# mongodb开启Debug模式
# MongoRepository
logging.level.org.springframework.data.mongodb.repository=DEBUG
# MongoTemplate
logging.level.org .springframework.data.mongodb.core= DEBUG

使用

使用流程

对于一门框架的使用,其使用顺序是非常关键的,因为有了大概的使用顺序,才能够处理好许多问题

设计好collections格式

这里的设计好指的是对一个实体类有大致的想法,而且能够满足需求,特别是一些细节的需求。

例如需要根据时间排序,那么这个collections就需要有一个时间戳Field

例如以下内容:

{
    "id":1,
    "name":"zhj",
    "age":18,
    "detail":"a good man",
    "timeStamp":"123"
}
//其中id是主键
编写实体类

实体类是非常关键的,Java作为一门面向对象语言,可以说哪里需要就需要new一个对象出来

这个实体类可以根据上一步的collections格式进行编写

@Document("user")
public class User implements Serializable {

    @Indexed(unique = true)
    @Field("id")
    private int id;
    @Field("name")
    private String name;
    @Field("age")
    private int age;
    @Field("detail")
    private String detail;

//setter && getter
//toString
}

关于这部分,有2个地方需要注意

  1. 其中有3个注解,分别是:

    @Document表示集合的名称,即集合user

    @Indexed表示主键,上面是以id为主键

    @Field](mailto:Indexed@Field)表示集合中的字段的键名,而private int id的值将会是字段id的值

  2. "_id"和"id"的区别

如果在实体类重定义了Field"_id"的话,如下:

@Document("user")
public class User implements Serializable {

    //不需要这个了:@Indexed(unique = true)
    @Field("_id")
    private int id;
	//setter && getter
	//toString
}

如果没有重定义Field“_id”的话,则每一次执行增加操作时,会自动生成一个字段,且其值是根据MongoDB的生成规则,如下:

"_id" : ObjectId("5f2ce4d3ad90594600115535")

这里不建议使用MongoDB的生成规则,因为有一些操作是需要主键的,例如删除,更新操作,如果使用MongoDB的生成规则,将无法进行获取并使用

所以建议选择第一种方式——先入为主

而且建议使用随机字符串+时间戳作为_id的值

实现MongoRepository接口
public interface UserRepository extends MongoRepository<User, String>{
    
}
创建Service层
@Service
public class UserService {
	@Autowired
	private UserRepository userRepository;
}
简单的增删改查
//repository层
//不用实现//使用自带的
//service层
// 增
public User saveOne(User user){
    try {
        return userRepository.save(user);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
//test层
@Test
void save() {
    User user = new User();
    user.setId(1);
    user.setName("zhj");
    user.setDetail("我是好人");
    user.setAge(21);
    User result = userService.saveOne(user);
    if(result!=null){
        System.out.println(result.toString());
    } else{
        System.out.println("插入失败");
    }
}
//结果//数据库会产生以下记录
{ 
    "_id" : ObjectId("5f2eb009dd289611253d8cf8"), 
    "id" : 1, 
    "name" : "zhj", 
    "age" : 21, 
    "detail" : "我是好人",
    "_class" : "pro.zhj.model.User" 
}
//注意以下返回值是int类型
//repository层
public int deleteOneById(int id);
//service层
// 删
public int deleteOne(int id){
    return userRepository.deleteOneById(id);
}
//test层
@Test
void delete() {
    int flag;
    flag = userService.deleteOne(2);
    System.out.println(flag);
}
//结果
1
//repository层
//无需实现
//service层
public User updateOne(User user){
    return userRepository.save(user);
}
//test层
@Test
void update() {
    User user = new User();
    user.setId(2);
    user.setName("小丑");
    user.setDetail("其实我也不是个坏人");
    user.setAge(25);
    User result = userService.updateOne(user);
    if(result!=null){
        System.out.println(result.toString());
    }else{
        System.out.println("更改失败");
    }
}
//结果
//原
{ "_id" : ObjectId("5f2eb24e1c3e41794ecbd89a"), "id" : 2, "name" : "小丑", "age" : 25, "detail" : "我是个坏人", "_class"
 : "pro.zhj.model.User" }
 //更改后
 { "_id" : ObjectId("5f2eb3829591964c8d347f51"), "id" : 2, "name" : "小丑", "age" : 25, "detail" : "其实我也不是个坏人",
"_class" : "pro.zhj.model.User" }
//repository层
public User findOneById(int id);
//service层
// 查
public User findOne(int id){
    return userRepository.findOneById(id);
}
//test层
@Test
void find() {
    User result = userService.findOne(1);
    if(result!= null){
        System.out.println(result.toString());
    }else{
        System.out.println("查找失败");
    }
}
//结果//控制台
//User{id=1, name='zhj', age=21, detail='我是好人'}

一些需求

基本上一些简单的增删改查就是上面的部分了。

当然实际开发中并不会这么简单,例如根据某个Field排序或者模糊查询等等。

或者分页的概念,那么就很需要下面的内容了。

Page分页

MongoRepository实现分页非常简单,使用Pageable即可

Repository层

@Query (...)
public Page<ItemLost> findAllUsers(Pageable pageable);

Service层

public List<ItemLost> findAllUsers(int page){
    int pageSize = 10;//每页10个元素
	Pageable pageable = PageRequest.of(page,pageSize);
	return userRepository.findAllUsers(pageable).getContent();
}
//注意:方法的返回类型

@Query

@Query注解可以说使用频繁了,一些复杂查询都可以使用@Query实现

例如上面说的模糊查询,比较查询,排序显示等等。

那么@Query注解下面有6个属性,其中3个:value、field和sort可以说是常用的

当然剩下3个也有用,但没有使用过,以后再进行补充。

value

属性value可以实现复杂查询,例如匹配查询、模糊查询、条件查询等等

匹配查询
@Query (value = "{'_id':?0}",fields = "{}")
public User findUserById(String id);
//以上内容表示根据 _id 进行查询
//其中?0表示的是第0个参数,就是方法内的第1个参数
//如果不设置,即表示查询全部
@Query (value = "{}",fields = "{}")
public User findUserById(String id);
模糊查询
@Query (value = "{'fileHead':?#{{$regex:[0]}}}",fields = "{}",sort = "{}")
public Page<FileDocument> findFileListByFileNameLike(String fileName,Pageable pageable);
//以上内容表示 根据fileHead进行模糊查询
//原本需求是:根据传入的文件名参数对collections的字段fileHead进行匹配
//其中关键词是:$regex
//为什么会这么写呢:是因为也是通过查询资料知道可以这样实现模糊查询,
//也即是参考链接中的@Query的使用,其中用到了EL表达式
条件查询

以上可以说是 只要知道需求,就可以根据上面的例子,直接进行书写
但是,有时一些需求就需要进行整理
例如 什么时候使用交集和并集的概念,即and 或者 or


//一个and
@Query (value="{'$and': [{'id':?0},{ 'timeStamp':{'$gte':?1}},{'iseffect':{'$lte':'2'}}]}")
public Page<User> findUserById(String id,String timeStamp,Pageable pageable);
//上面的内容表示的是:
//and的概念,即必须满足以下内容:
//1.id==参数id
//2.timeStamp >=  参数timeStamp//gte大于等于
//3.iseffect <= 2//lte表示小于等于

//and 和 or 同时使用
@Query (value = "{'$and': [{'$or': [{ 'lostName':?#{{$regex:[0]}}},{ 'lostAdress':?#{{$regex:[0]}}}]},{ 'timeStamp':{'$gte':?1}},{'iseffect':'3'}]}")
public Page<ItemLost> findItemsByKeyWord(String keyWord,String timeStamp,Pageable pageable);
//其实只要掌握了其中的一种之后,复杂的就是组合,就是所谓的组装。
//首先完成 一个or 完成之后,将or看成是一个条件 然后和另一个条件完成and
对象查询

为什么会提到这个呢,是因为Java是一门面向对象语言,往往有时是定义collections不仅仅只是使用到一些基本的数据类型,还会可以使用到自定义的对象,例如:

//联系
class Call{
	private String type;//联系方式
    private String call;//联系号码
} 
@Document("user")
public class User{
    @Field("_id")
    private String id;
    @Field('call')
    private Call call;
    ...
}

那么如果有一个需求:获取联系方式为callType的所有用户,则可以这样写

@Query (value = "{'call.type':?0}",fields = "{}")
public Page<User> findUserByCallType(String callType);
//即使用call.type表示call对象的type属性

如果参数是一个对象,则可以这么写

@Query (value = "{'call.type':?0.call.type}",fields = "{}")
public Page<User> findUserByCallType(User user);
//即使用call.type表示call对象的type属性
//即找到跟参数user对象相同的联系方式的所有用户
更多

当然以后可能会遇到更加复杂的需求,那么关键在于value属性值的添加。

一般而言,可以根据上面的例子进行组装,当然如果无法获取解决方案,

那么如何知道呢,其实可以去看MongoDB的一些查询语句,就可以得到启发。

可以到这里进行学习:菜鸟教程-MongoDB查询

fields

相比属性value,fields的功能性就比较单一了——控制字段的显示

@Query (value = "{'_id':?0}",fields = "{'username':1,'passwd':0}")
public User findUserById(String id);
//以上的fields表示的是显示username,不显示passwd

这里的不显示不是说直接整个字段不显示,而是将该字段的值设置为null;

{
    "id":1,
    "userName":"zhj",
	"passwd":null,
    "timeStamp":"123"
}

题外话:

这有什么用呢,怎么说呢,我觉得有一个作用——安全和资源

其一:安全

一般而言,后端开发总是前后端分离,那么接口肯定会有可能暴露,

如果不控制字段的显示,显示全部字段内容,那么将会对安全有非常大的危险。

例如恶意删除,恶意调用等等,所以可以对于一些未使用到的敏感字段进行隐藏。

特别是:微信小程序项目开发。

其二:资源:

如果每一个请求都显示大量的无用字段,即业务对于该字段并没有进行利用,那么如果请求返回太多的话,也是对资源的一种浪费。

sort

一般而言sort都是根据时间进行排序,所以非常推荐设计一个字段存储时间戳

当进行查询的时候再根据这个字段进行排序

@Query (value = "{}",fields = "{}",sort = "{timeStamp:-1}")
public Page<User> findUserSortByCreateTimeDESC(Pageable pageable);
//以上表示根据创建时间进行倒序排列
//-1 表示 desc
//1 表示 asc

sort的功能其实也可以像value的一样的,

例如根据某个字段进行排序,如果当某个字段相同时,再根据某个字段排序

以后如果有遇到,再进行记录

总结

以上内容都是对于MongoDB的使用经历,基本可以满足一般的开发需求了。

如果以后还遇到一些另外的需求,再进行补充。

另外,后面会做一篇关于MongoTemplate的。

  • 15
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 当你在Spring Boot项目中使用MongoDB时,需要遵循以下步骤: 1.添加Maven依赖项:添加Spring Data MongoDB依赖项。 2.配置数据源:在application.properties文件中添加MongoDB连接的URL,数据库名称,用户名和密码等信息。 3.创建实体类:创建一个代表MongoDB集合的Java类,并使用@Document注释指定MongoDB集合的名称。 4.创建存储库接口:创建一个扩展MongoRepository接口的接口,并提供实体类和主键类型作为泛型参数。该接口将自动生成CRUD操作。 5.编写服务类:编写一个包含用于调用存储库接口的方法的服务类。 6.使用控制器:编写一个控制器类,使用@Service注释注入服务类,并使用@RequestMapping注释定义REST端点。 7.运行应用程序:运行应用程序,使用Postman或浏览器等工具测试REST API。 以上是使用Spring Boot操作MongoDB的基本步骤,具体细节可以根据实际情况进行调整。 ### 回答2: ### 回答3: Spring Boot是一个自带快速构建项目的框架,也是与MongoDB数据库结合的良好选择。MongoDB作为一种流行的非关系型数据库,提供了高可扩展性和高性能。在Spring Boot中使用MongoDB进行数据存储,可以通过配置文件和自动化依赖项简化该过程。 一、引入MongoDB依赖项 在项目的build.gradle文件中,添加对spring-boot-starter-data-mongodb依赖项的引入。这样做可以为项目提供连接到MongoDB所需的所有类和方法。 dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' } 二、MongoDB配置 打开application.properties文件,以便在该文件中配置MongoDB连接。在该文件中加入以下所需配置即可: spring.data.mongodb.host=localhost #MongoDB服务主机的名称或IP地址 spring.data.mongodb.port=27017 #MongoDB服务端口 spring.data.mongodb.database=test #用于连接的MongoDB数据库的名称 三、MongoDBRepository 在使用MongoDB时,需要创建一个Repository来管理MongoDB中的文档。可以简单地扩展MongoRepository接口来访问MongoDB的数据。以下是一个例子: package com.example.demo.repository; import com.example.demo.model.User; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends MongoRepository<User, String> { } 这个UserRepository接口扩展了MongoRepository,并在GenericType中指定了User类和其ID类型。所有CRUD操作都可以从该Repository中实现。 四、使用MongoDB 现在可以将MongoDBSpring Boot项目集成。在需要访问MongoDB的类中注入UserRepository即可通过该Repository来执行CRUD操作。 @Service public class UserService { @Autowired UserRepository userRepository; // 获取所有用户 public List<User> getAllUsers() { return userRepository.findAll(); } // 通过ID获取用户 public User getUserById(String id) { return userRepository.findById(id).orElseThrow(() -> new UserNotFoundException(id)); } // 插入新用户 public User addUser(User user) { return userRepository.save(user); } // 通过ID删除用户 public void deleteUser(String id) { userRepository.deleteById(id); } } 以上是一个简单的示例,展示了如何使用Spring BootMongoDB对用户执行CRUD操作。 总之,使用Spring BootMongoDB构建Java Web项目是一种流行的选择,因为它能够简化代码开发和配置,提高生产效率。通过上述简单的步骤和代码示例,可以轻松优雅地完成与MongoDB的开发、部署和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值