mongodb-java apispringboot整合mongodb

news2024/10/6 1:45:50
  • mongodb入门
  • mongodb-java api的使用
  • springboot整合mongodb
  • 评论

一 MongoDB

1.1 MongoDB简介

​ MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

​ MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。

​ MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

官网:https://www.mongodb.com

1.2 MongoDB安装

1.2.1 windows安装mongodb

官网下载mongodb安装包

https://www.mongodb.com/try/download/community

1 将mongodb压缩包解压到指定目录即可

2 配置环境变量 将mongodb/bin目录配置到path中

在这里插入图片描述

3 启动 ,双击bin/mongod.exe

如果启动时,报错

在这里插入图片描述

说明是mongodb启动时会默认加载这个路径作为存储数据的地方,而当前路径没有,就需要手动新建一个目录

4 启动完成以后,可以双击mongo.exe,打开命令行连接本机mongodb,测试本机mongodb是否启动成功

在这里插入图片描述

1.2.2 docker安装mongodb
# 安装mongodb容器
docker run  -id --name=mongodb --hostname=mongodb -p 27017:27017 mongo

# 进入mongodb容器
docker exec -it mongodb /bin/bash

# 进入mongodb命令行
mongo

# 查看当前mongodb中所有的数据库
show dbs

# 安装mongodb容器并设置用户名,密码
docker run  -id --name=mongodb --hostname=mongodb -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=123456 mongo

# mongodb设置了密码以后,怎么连接?
docker exec -it mongodb /bin/bash   # 进入mongodb容器
mongo    # 进入mongodb命令行
use admin    # 切换到admin数据库
db.auth("用户名","密码")  # 输入用户名和密码,如果返回1就说明登录成功

1.3 MongoDB基本使用

1.3.1 基本概念

在使用Mongodb以前,为了方便理解,先对应关系型数据库了解下相关概念

sql概念mongodb概念说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据行/文档
columnfield列/字段
indexindex索引
table joins表关联,mongodb不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

在这里插入图片描述

1.3.2 数据库和表操作

查看所有数据库 show dbs

> show dbs
admin  0.000GB
local  0.000GB

切换数据库 use 数据库名

> use admin
switched to db admin

创建数据库和表

在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库和表

# 查看所有的数据库,当前没有test数据库
> show dbs
admin  0.000GB
local  0.000GB

# 切换到test数据库
> use test
switched to db test

# 再次查看所有数据库,还是没有test,说明use只是切换数据库,不会创建数据库
> show dbs
admin  0.000GB
local  0.000GB

# 直接向test数据库中的user表插入数据
> db.user.insert({id:1,name:"zhangsan"})
WriteResult({ "nInserted" : 1 })

# 查看所有数据库,当前有了test数据库
> show dbs
admin  0.000GB
local  0.000GB
test   0.000GB

删除数据库

> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
> show dbs
admin  0.000GB
local  0.000GB

查看所有的表 show tables/collections

> show tables
user
> show collections
user

删除表 drop

> db.user.drop()
true
> show tables
1.3.3 文档操作
1.3.3.1 新增数据

insert/save 如果当前没有这个表,那么当第一次新增数据时,会自动新建表

> db.user.insert({id:1,name:"zhangsan"})
WriteResult({ "nInserted" : 1 })
> db.user.save({id:2,name:"lisi"})
WriteResult({ "nInserted" : 1 })
> db.user.find()
{ "_id" : ObjectId("6638c98397dbe43ebeabeadf"), "id" : 1, "name" : "zhangsan" }
{ "_id" : ObjectId("6638c98f97dbe43ebeabeae0"), "id" : 2, "name" : "lisi" }
1.3.3.2 更新数据
db.表名.update({query},{set})
query: 就相当于sql中写在where条件后面
set : 就是修改后的字段值,相当于Sql中set 

# 更新数据,更新id=1的name为zs
> db.user.update({id:1},{$set:{name:"zs"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("6638c98397dbe43ebeabeadf"), "id" : 1, "name" : "zs" }
{ "_id" : ObjectId("6638c98f97dbe43ebeabeae0"), "id" : 2, "name" : "lisi" }

# 更新id=2的数据,年龄为30,但是其他字段都会删除掉
> db.user.update({id:2},{age:30})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("6638c98397dbe43ebeabeadf"), "id" : 1, "name" : "zs" }
{ "_id" : ObjectId("6638c98f97dbe43ebeabeae0"), "age" : 30 }

# 更新id=1的数据,age=35,如果age字段不存在,会默认新增该字段
> db.user.update({id:1},{$set:{age:35}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("6638c98397dbe43ebeabeadf"), "id" : 1, "name" : "zs", "age" : 35 }
{ "_id" : ObjectId("6638c98f97dbe43ebeabeae0"), "age" : 30 }
1.3.3.3 删除数据
# 删除id=1
> db.user.remove({id:1})
WriteResult({ "nRemoved" : 1 })
> db.user.find()
{ "_id" : ObjectId("6638c98f97dbe43ebeabeae0"), "age" : 30 }

# 删除所有
> db.user.remove({})
WriteResult({ "nRemoved" : 1 })
> db.user.find()
1.3.3.4 查询数据
#查询语句结构
db.user.find([query],[fields])

query 是查询的条件
fields 是查询的字段

# 造数据
> db.user.insert({id:1,name:"zs",age:20})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:2,name:"ls",age:35})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:3,name:"ww",age:28})
WriteResult({ "nInserted" : 1 })
> db.user.insert({id:4,name:"zl",age:32})
WriteResult({ "nInserted" : 1 })

# 查询所有
> db.user.find()
{ "_id" : ObjectId("6638cc3497dbe43ebeabeae5"), "id" : 1, "name" : "zs", "age" : 20 }
{ "_id" : ObjectId("6638cc3d97dbe43ebeabeae6"), "id" : 2, "name" : "ls", "age" : 35 }
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww", "age" : 28 }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl", "age" : 32 }

# 只查询id,name字段
> db.user.find({},{id:1,name:1})
{ "_id" : ObjectId("6638cc3497dbe43ebeabeae5"), "id" : 1, "name" : "zs" }
{ "_id" : ObjectId("6638cc3d97dbe43ebeabeae6"), "id" : 2, "name" : "ls" }
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww" }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl" }

# 查询条数
> db.user.find().count()
4

# 查询ID=1的数据
> db.user.find({id:1})
{ "_id" : ObjectId("6638cc3497dbe43ebeabeae5"), "id" : 1, "name" : "zs", "age" : 20 }

# 查询年龄在25-35之间的数据
> db.user.find({age:{$lte:35,$gte:25}})
{ "_id" : ObjectId("6638cc3d97dbe43ebeabeae6"), "id" : 2, "name" : "ls", "age" : 35 }
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww", "age" : 28 }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl", "age" : 32 }

# 查询年龄<=35,且id>=3的
> db.user.find({age:{$lte:35},id:{$gte:3}})
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww", "age" : 28 }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl", "age" : 32 }

# 查询id=1 or id=2的数据
> db.user.find({$or:[{id:1},{id:2}]})
{ "_id" : ObjectId("6638cc3497dbe43ebeabeae5"), "id" : 1, "name" : "zs", "age" : 20 }
{ "_id" : ObjectId("6638cc3d97dbe43ebeabeae6"), "id" : 2, "name" : "ls", "age" : 35 }

# 分页查询  skip()跳过几条数据,可以理解为从第几条开始查询  limit()查询的条数
> db.user.find().skip(2).limit(2)
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww", "age" : 28 }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl", "age" : 32 }

# 按照年龄倒序排  -1倒序排列  1 正序排列
> db.user.find().sort({age:-1})
{ "_id" : ObjectId("6638cc3d97dbe43ebeabeae6"), "id" : 2, "name" : "ls", "age" : 35 }
{ "_id" : ObjectId("6638cc5797dbe43ebeabeae8"), "id" : 4, "name" : "zl", "age" : 32 }
{ "_id" : ObjectId("6638cc4897dbe43ebeabeae7"), "id" : 3, "name" : "ww", "age" : 28 }
{ "_id" : ObjectId("6638cc3497dbe43ebeabeae5"), "id" : 1, "name" : "zs", "age" : 20 }
1.3.4 索引操作

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取

那些符合查询条件的记录。

这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站

的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排

序的一种结构

# 查看索引  说明:1表示升序创建索引,-1表示降序创建索引。
> db.user.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.user"
    }
]

# 创建索引 按照年龄升序创建索引
> db.user.createIndex({age:1})
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> db.user.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.user"
    },
    {
        "v" : 2,
        "key" : {
            "age" : 1
        },
        "name" : "age_1",
        "ns" : "test.user"
    }
]


#删除索引
db.user.dropIndex("age_1")
#或者,删除除了_id之外的索引
db.user.dropIndexes()

#创建联合索引
db.user.createIndex({'age':1, 'id':-1})

#查看索引大小,单位:字节
db.user.totalIndexSize()

1.4 Mongodb图形客户端的使用

1.4.1 安装mongoDB客户端

Robo 3T是MongoDB的客户端工具,我们可以使用它来操作MongoDB。

在这里插入图片描述

注意:如果连接的是远程云服务器的话,一定要在安全组中放行mongodb的端口27017

1.4.2 客户端基本使用

在这里插入图片描述

在这里插入图片描述

二 java操作MongoDB

1 javaApi操作MongoDB

导依赖

    <dependencies>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-sync</artifactId>
            <version>3.9.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>
    </dependencies>
1.1 文档操作

连接MongoDB

@Test
    public void test() throws Exception{
        // 创建MongoDb客户端
        MongoClient mongoClient = MongoClients.create("mongodb://root:123456@116.205.236.142:27017");

        // 选择要操作的数据库
        MongoDatabase database = mongoClient.getDatabase("test");

        // 选择要操作的表
        MongoCollection<Document> collection = database.getCollection("user");

        System.out.println(collection);

        // 关闭客户端连接
        mongoClient.close();
    }

文档crud

public class MongodbTest {

    private static MongoClient mongoClient = null;

    public MongoCollection<Document> getCollection() throws Exception{
        // 创建MongoDb客户端
        mongoClient = MongoClients.create("mongodb://116.205.236.142:27017");

        // 选择要操作的数据库
        MongoDatabase database = mongoClient.getDatabase("test");

        // 选择要操作的表
        MongoCollection<Document> collection = database.getCollection("user");

        System.out.println(collection);

        return collection;
    }

    @Test
    public void testAdd() throws Exception{
        // 连接mongodb,获取要操作的表
        MongoCollection<Document> collection = getCollection();

        // 构造要新增的数据
        Document document = new Document("id", 5).append("name", "tq").append("age", 24);

        // 插入数据
        collection.insertOne(document);

        // 关闭客户端连接
        mongoClient.close();
    }

    @Test
    public void testUpdate() throws Exception{
        // 连接mongodb,获取要操作的表
        MongoCollection<Document> collection = getCollection();

        // 构建修改的条件
        Bson bson = Filters.eq("id", 5);

        // 构建修改后的对象
        Bson bson1 = Updates.set("age", 26);

        // 修改数据
        collection.updateOne(bson,bson1 );

        // 关闭客户端
        mongoClient.close();
    }

    @Test
    public void testDelete() throws Exception{
        // 连接mongodb,获取要操作的表
        MongoCollection<Document> collection = getCollection();

        // 删除id=5的数据
        collection.deleteOne(Filters.eq("id", 5));

        // 关闭客户端
        mongoClient.close();
    }

    @Test
    public void testQuery() throws Exception{
        // 连接mongodb,获取要操作的表
        MongoCollection<Document> collection = getCollection();

        // 查询所有数据
        FindIterable<Document> documents = collection.find();
        for (Document document : documents) {
            System.out.println(document);
        }
        System.out.println("==============================================");
        // 查询age在25-35之间的,按照年龄倒序排列,且分页查询
        FindIterable<Document> documents1 = collection.find(
                Filters.and(
                        Filters.lte("age", 35),
                        Filters.gte("age", 25)
                )

        ).sort(Sorts.descending("age")).skip(0).limit(2);
        for (Document document : documents1) {
            System.out.println(document);
        }

        // 关闭客户端
        mongoClient.close();
    }
}
1.2 操作对象

定义要操作的员工类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {

    private Long id;
    private String name;
    private Integer age;
    private String intro;
    private Integer sex;

}

crud操作

public class EmployeeTest {

    private static MongoClient mongoClient = null;

    public MongoCollection<Employee> getCollection() throws Exception{
        //定义对象的解码注册器
        CodecRegistry pojoCodecRegistry = CodecRegistries.
                fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                        CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
                );

        // 创建MongoDb客户端
        mongoClient = MongoClients.create("mongodb://116.205.236.142:27017");

        // 选择要操作的数据库
        MongoDatabase database = mongoClient.getDatabase("test").withCodecRegistry(pojoCodecRegistry);;

        // 选择要操作的表
        MongoCollection<Employee> collection = database.getCollection("employee", Employee.class);

        System.out.println(collection);

        return collection;
    }

    @Test
    public void testAdd() throws Exception{
        Employee employee = new Employee(1L, "zhangsan", 30, "张三是一个好员工", 1);

        MongoCollection<Employee> collection = getCollection();

        collection.insertOne(employee);

        mongoClient.close();
    }

    @Test
    public void testUpdate() throws Exception{
        MongoCollection<Employee> collection = getCollection();

        collection.updateOne(Filters.eq("_id", 1), Updates.set("name", "张三"));

        mongoClient.close();
    }

    @Test
    public void testFind() throws Exception{
        MongoCollection<Employee> collection = getCollection();

        for (Employee employee : collection.find(Filters.eq("age", 30))) {
            System.out.println(employee);
        }

        mongoClient.close();
    }

    @Test
    public void testDelete() throws Exception{
        MongoCollection<Employee> collection = getCollection();

        collection.deleteOne(Filters.eq("_id",1));

        mongoClient.close();
    }

}

2 spring-data-mongodb

spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作。

springboot spring data mongodb 就是在springboot项目中使用spring data mongodb

导入依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>

     <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

配置application.yml配置文件

spring:
  application:
    name: springboot-mongodb-demo
  data:
    mongodb:
      uri: mongodb://127.0.0.1:27017/test1

启动类

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

测试类测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class MongodbTest {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    public void testAdd() throws Exception{
        Employee employee = new Employee(1L, "张三", 30, "张三是个好员工", 1);
        mongoTemplate.save(employee);
    }

    @Test
    public void testGetAll() throws Exception{
        List<Employee> employees = mongoTemplate.findAll(Employee.class);
        System.out.println(employees);
    }

    @Test
    public void testUpdate() throws Exception{
        Employee employee = new Employee(1L, "张三1", 28, "张三1是个好员工", 1);
        Query query = Query.query(Criteria.where("id").is(employee.getId()));

        Update update = new Update().set("name", employee.getName())
                .set("age", employee.getAge())
                .set("intro", employee.getIntro())
                .set("sex", employee.getSex());

        mongoTemplate.updateFirst(query,update,Employee.class);
    }

    @Test
    public void testDelete() throws Exception{
        Query query = Query.query(Criteria.where("id").is(1));

        mongoTemplate.remove(query,Employee.class);
    }
}

评论功能

用户可以对看上的车辆提问,别的用户或者销售人员可以针对用户的提问进行回复。

需要实现的功能:

​ 发表评价

​ 回复评论

​ 展示该商品的评论

​ 删除评论/回复

  • 基于mongodb 将评论数据存放在mongodb中

    1. 模式自由:MongoDB是一个面向文档的数据库,这意味着它不使用固定的表结构,而是使用灵活的文档模型来存储数据。在商品评论场景中,评论的字段可能会随着业务的发展而发生变化,使用MongoDB可以更加灵活地应对这种变化,而无需修改整个数据库结构。
    2. 高性能:MongoDB的查询性能通常优于传统关系型数据库,尤其是在处理大量数据时。对于商品评论系统来说,可能需要存储和检索大量的评论数据,MongoDB的高性能可以确保系统的响应速度和稳定性。
    3. 可扩展性:MongoDB支持分布式存储和自动分片,可以轻松实现横向扩展。这意味着当评论数据量增长时,可以通过添加更多的服务器来扩展存储容量和查询性能,而无需停机或中断服务。
    4. 易用性:MongoDB使用BSON(二进制JSON)格式存储数据,数据以文档的形式组织,类似于JSON对象。这使得数据的存储和检索更加直观和易于理解,降低了开发难度。
    5. 数据一致性:MongoDB支持数据复制和冗余存储,以提供高可用性和数据备份。这意味着即使发生硬件故障或网络问题,也可以保证数据的完整性和一致性,从而确保商品评论系统的稳定性和可靠性。

MongoDB的模式自由、高性能、可扩展性、易用性和数据一致性等特点使其成为商品评论功能中存储数据的理想选择。然而,具体是否使用MongoDB还需要根据项目的实际需求和技术栈来决定

2 后端实现

domain

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Comment {

    private String id;
    private Long userId;
    private String username;
    private Long carId;
    private String content;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date commentTime;
    private List<CommentReplies> replies;
}




@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommentReplies {

    private String id;
    private Long userId;
    private String username;
    private String content;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date repliesTime;
}

dto

@Data
public class AddRepliesDTO {

    private String commentId;
    private Long userId;
    private String username;
    private String content;

}

controller

@RestController
@RequestMapping("/comment")
public class CommentController {

    @Autowired
    private ICommentService commentService;

    @PutMapping
    public AjaxResult addOrUpdate(@RequestBody Comment comment){
        if(Objects.nonNull(comment.getId())){
            commentService.update(comment);
        }else{
            commentService.add(comment);
        }
        return AjaxResult.me();
    }

    @DeleteMapping
    public AjaxResult deleteById(String id){
        commentService.deleteById(id);
        return AjaxResult.me();
    }

    @GetMapping("/carId/{carId}")
    public AjaxResult getByCarId(@PathVariable("carId")Long carId){
        List<Comment> list = commentService.getByCarId(carId);
        return AjaxResult.me().setData(list);
    }

    @PutMapping("/addReplies")
    public AjaxResult addReplies(@RequestBody AddRepliesDTO dto){
        commentService.addReplies(dto);
        return AjaxResult.me();
    }
}

service

@Service
public class CommentServiceImpl implements ICommentService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void add(Comment comment) {
        comment.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        comment.setCommentTime(new Date());
        mongoTemplate.save(comment);
    }

    @Override
    public void update(Comment comment) {
        Query query = Query.query(Criteria.where("id").is(comment.getId()));

        Update update = new Update().set("content", comment.getContent())
                .set("commentTime", new Date());
        mongoTemplate.updateFirst(query,update,Comment.class);
    }

    @Override
    public void deleteById(String id) {
        Query query = Query.query(Criteria.where("id").is(id));

        mongoTemplate.remove(query,Comment.class);
    }

    @Override
    public List<Comment> getByCarId(Long carId) {
        Query query = Query.query(Criteria.where("carId").is(carId));
        query.with(Sort.by(Sort.Direction.DESC, "commentTime"));
        List<Comment> list = mongoTemplate.find(query, Comment.class);
        return list;
    }

    @Override
    public void addReplies(AddRepliesDTO dto) {
        Comment comment = mongoTemplate.findById(dto.getCommentId(), Comment.class);
        CommentReplies commentReplies = new CommentReplies();
        BeanUtils.copyProperties(dto, commentReplies);
        commentReplies.setRepliesTime(new Date());
        commentReplies.setId(UUID.randomUUID().toString().replaceAll("-", ""));

        List<CommentReplies> replies = comment.getReplies();
        if(replies == null){
            replies = new ArrayList<>();
        }
        replies.add(commentReplies);


        Query query = Query.query(Criteria.where("id").is(comment.getId()));

        Update update = new Update().set("replies", replies);
        mongoTemplate.updateFirst(query,update,Comment.class);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1827053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java——可变参数

一、可变参数 1、介绍 Java的可变参数&#xff08;Varargs&#xff09;是一种语法特性&#xff0c;允许一个方法接受不定数量的参数。可变参数的使用通过在参数类型后面添加省略号&#xff08;...&#xff09;实现。这使得方法在调用时可以传入不同数量的参数&#xff0c;而不…

【靶场搭建】-01- 在kali上搭建DVWA靶机

1.DVWA靶机 DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是使用PHPMysql编写的web安全测试框架&#xff0c;主要用于安全人员在一个合法的环境中测试技能和工具。 2.下载DVWA 从GitHub上将DVWA的源码clone到kali上 git clone https://github.com/digininj…

新机器到底是入手DDR5还是DDR4?2024年的DDR5能否战未来?

前言 前几天有个小伙伴发来问候&#xff1a;在今年&#xff08;2024年&#xff09;装新机器到底是选择DDR4还是DDR5&#xff1f; 小白淡定了抿了一口茶&#xff0c;缓缓道&#xff1a;…… 小伙伴不淡定了&#xff01;上来就是一句&#xff1a;2024年的DDR5能否战未来&#…

用一个ESP32S3-Zero把有线键盘变为无线

三脚猫最近一直琢磨&#xff0c;那些喜欢买剪线键盘&#xff0c;以及自制键盘瞎折腾的人都是怎么搞的。经过不懈努力&#xff0c;终于想明白除了直接的硬件一个个pin针的高低电压判断后转给蓝牙&#xff0c;拿到现成的古董剪线键盘还有一个方式其实是在usb host转发给蓝牙类似这…

凭什么只有我不能触摸她的心?JavaScript的作用域?作用域链?预编译?

前言 凭什么后来者居上&#xff1f;凭什么她的心只有我不能触摸&#xff1f;&#xff08;o(╥﹏╥)o&#xff09; 让我从JavaScript中的作用域、作用域链和预编译开始聊聊&#xff0c;相信你一定能从中有收获的 什么是的作用域&#xff1f; 简单来说就是能被访问的区域&…

ROS-SLAM雷达

使用前准备工作 1、新建工作空间、编译功能包 以建立名字为rplidar_ws为例&#xff0c;终端输入 mkdir rplidar_ws cd rplidar_ws mkdir src cd src catkin_init_workspace rplidar_ros功能包&#xff1a;git下载。 https://github.com/Slamtec/rplidar_ros/ 然后把解压的…

vue(v-if,v-else-if-else-show)

基本应用 例子 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTE-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-w…

斯坦福ALOHA机器人团队最新论文-HumanPlus: 从人类学习的人形机器人动作模仿和自主操作

斯坦福ALOHA机器人团队最新论文-HumanPlus&#xff0c;继续推进了机器人技术的前沿进展&#xff0c;我进行了部分翻译和解读&#xff1a; HumanPlus人形机器人系统技术解读 1 简介 本教程将介绍一个名为HumanPlus的全栈式人形机器人系统。该系统能够让机器人从人类数据中学习…

面向事件编程之观察者模式

前言 村里的老人常说&#xff1a;真男人就该懂得遵守“三不原则”——不主动、不拒绝、不负责。 一个复杂的软件系统&#xff0c;其中必然会存在各种各样的“对象”&#xff0c;如果在设计之初没有注意控制好耦合度&#xff0c;导致各个对象甚至是函数之间高度耦合&#xff0…

如何用 Google Chrome 浏览器浏览经过 XSLT 渲染的XML 文件

对于经过 XSLT 渲染的XML 文件&#xff0c;本来&#xff0c;可以直接用 IE (Internet Explorer) 打开&#xff0c;就能看到渲染之后的样子&#xff0c;很方便。但是后来&#xff0c;微软把 IE 换成了 Microsoft Edge&#xff0c;按理说这是比 IE 更先进的浏览器&#xff0c;可是…

centos7系统使用docker-compose安装部署jenkins

CentOS7系统使用docker-compose安装部署jenkins&#xff0c;并实现前后端自动构建 记录一次在给公司部署jenkins的真实经历&#xff0c;总结了相关经验 1.准备环境 1.java 由于最新的jenkins需要jdk11以上才能支持&#xff0c;而系统里的jdk是1.8的&#xff0c;因此等jenkins…

qmt交易框架2.0版本----支持实时高频交易

经过了2个星期的开发&#xff0c;终于迎来了qm交易框架2.0&#xff0c;超过了3000行源代码&#xff0c;使用类开发&#xff0c;使用方便。 我们看看利用框架写一个简单的实时高频交易策略&#xff0c;很简单 源代码 from qmt_trader.qmt_trader import qmt_traderfrom qmt_tr…

工业 web4.0 的 UI 卓越非凡

工业 web4.0 的 UI 卓越非凡

求导,积分

求导公式&#xff1a; 复合函数求导法则&#xff1a;两个函数导函数的乘积. 例如&#xff1a;f(x)2x1,f(x)2,g(x)x^24x4,g(x)2x4 那么复合函数&#xff1a; g(f(x))(2x1)^24(2x1)4 把&#xff08;2x1&#xff09;看做整体,则g2(2x1)4 然后再求&#xff08;2x1&#xff09;的导函…

代码随想录算法训练营刷题复习1 :动态规划背包问题 01背包+完全背包

动态规划刷题复习 一、01背包 416. 分割等和子集1049. 最后一块石头的重量 II494. 目标和474. 一和零 416. 分割等和子集 class Solution { public:bool canPartition(vector<int>& nums) {int sum0;for(int i0;i<nums.size();i) {sumnums[i];}if(sum%2!0)retu…

Tuple 元组

文章目录 一、什么是元组 &#xff1f;二、元组的具体操作2.1 创建元组2.1.1 tuple() 创建元组函数和 list() 创建列表函数总结 2.2 元组的元素访问操作2.3 元组的元素计数操作2.4 zip 对象 一、什么是元组 &#xff1f; 列表属于可变序列,可以任意修改列表中的元素。 元组的…

JUC并发编程-第二天:线程池相关

线程池相关 线程池内置线程池的使用线程池的关闭excute方法和submit方法的区别 线程池 线程池就是一个可以复用线程的技术 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,Thread…

HTML静态网页成品作业(HTML+CSS)——游戏永劫无间网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有3个页面。 二、作品演示 三、代…

初见 Rollup 的十大常见问题

文章目录 初见 Rollup 的十大常见问题1. 超神奇的 Rollup 英文解释&#xff01;2. 为什么 ESM 要比 CommonJS 要好呢&#xff1f;3. 什么是 tree-shaking ?4. 如何使用 Rollup 处理 CommonJS&#xff1f;5. 为什么 node-resolve 不是一个内置功能&#xff1f;6. 为什么在进行代…

网络协议,OSI,简单通信,IP和mac地址

认识协议 1.讲故事 2004年&#xff0c;小明因为给他爹打电话&#xff08;座机&#xff09;费用太贵&#xff0c;所以约定一种信号&#xff0c;响一次是报平安&#xff0c;响两次是要钱&#xff0c;响三次才需要接通。 2.概念 协议&#xff1a;是一种约定&#xff0c;这种约…