Java研学-MongoDB(四)

发布于:2025-07-12 ⋅ 阅读:(21) ⋅ 点赞:(0)

一 环境搭建

1 导入依赖

  生成springboot项目后倒入所需要的mongodb依赖

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

2 数据库表 – 测试数据

dahuang> db.comment.find()
[
  {
    _id: ObjectId('685a3f60576e6446ef6c4bd0'),
    content: '齐夏这波操作简直6到飞起,不愧是「回响」界的扛把子!',
    publishtime: ISODate('2025-06-24T11:27:27.000Z'),
    userid: '1001',
    nickname: '齐夏的小迷弟',
    createdatetime: ISODate('2025-06-24T11:27:27.260Z'),
    likenum: 42,
    replynum: 8,
    state: '1',
    parentid: null,
    articleid: '100000'
  },
  {
    _id: ObjectId('685a3f60576e6446ef6c4bd1'),
    content: '乔家劲大佬又双叒叕carry全场,这波「天龙」直接封神!',
    publishtime: ISODate('2025-06-24T11:27:28.000Z'),
    userid: '1002',
    nickname: '劲哥的狗腿子',
    createdatetime: ISODate('2025-06-24T11:27:28.260Z'),
    likenum: 66,
    replynum: 12,
    state: '1',
    parentid: null,
    articleid: '100001'
  },
  {
    _id: ObjectId('685a3f60576e6446ef6c4bd2'),
    content: '林檎小姐姐的「回响」太绝了,直接把BOSS秀到头皮发麻!',
    publishtime: ISODate('2025-06-24T11:27:29.000Z'),
    userid: '1003',
    nickname: '檎檎的舔狗',
    createdatetime: ISODate('2025-06-24T11:27:29.260Z'),
    likenum: 33,
    replynum: 5,
    state: '1',
    parentid: null,
    articleid: '100002'
  },
  {
    _id: ObjectId('685a3f60576e6446ef6c4bd3'),
    content: '陈俊南这波嘴炮输出直接拉满,BOSS都被他说得怀疑人生了!',
    publishtime: ISODate('2025-06-24T11:27:30.000Z'),
    userid: '1004',
    nickname: '南哥的捧哏',
    createdatetime: ISODate('2025-06-24T11:27:30.260Z'),
    likenum: 55,
    replynum: 10,
    state: '1',
    parentid: null,
    articleid: '100003'
  },
  {
    _id: ObjectId('685a3f60576e6446ef6c4bd4'),
    content: '程雪的「回响」太治愈了,直接把队友从残血奶到满血!',
    publishtime: ISODate('2025-06-24T11:27:31.000Z'),
    userid: '1005',
    nickname: '雪姐的迷妹',
    createdatetime: ISODate('2025-06-24T11:27:31.260Z'),
    likenum: 28,
    replynum: 4,
    state: '1',
    parentid: 10086,
    articleid: '100004'
  }
]

3 项目截图

在这里插入图片描述

4 配置文件

spring:
  data:
    mongodb:
      # 主机IP地址,此处本机
      host: localhost
      # 数据库名称
      database: dahuang
      # 端口(默认是 27017,可省略)
      port: 27017

5 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
// 指定 MongoDB 集合名 若与类名相同可省略 MongoDB 的集合名是区分大小写的
@Document(collection = "comment")
// 复合索引
@CompoundIndexes({
    @CompoundIndex(name = "userid_nickname_idx", def = "{'userid': 1, 'nickname': -1}")
})
public class Comment implements Serializable {
    @Id // 标记为主键,对应 MongoDB 的 "_id" 字段
    private String id;
    @Field("content") // 指定 MongoDB 字段名
    private String content; // 吐槽内容
    private Date publishtime; // 发布日期
    @Indexed // 添加单字段索引
    private String userid; // 发布人 ID
    private String nickname; // 昵称
    private LocalDateTime createdatetime; // 评论的日期时间
    private Integer likenum; // 点赞数
    private Integer replynum; // 回复数
    private String state; // 状态
    private String parentid; // 上级 ID(回复的评论 ID)
    private String articleid; // 关联的文章 ID
}

6 继承 MongoDB 仓库接口

// CommentRepository 是一个 Spring Data MongoDB 仓库接口 拥有基本的 CRUD 操作
public interface CommentRepository extends MongoRepository<Comment, String> {
    // Comment:实体类类型,表示该仓库操作的文档类型。
    // String:主键(_id)的类型,这里是 String 类型。
}

7 Service 层 – 测试方法

@Service
public class CommentService {
    private final CommentRepository commentRepository;

    public CommentService(CommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }

    // 保存评论
    public void saveComment(Comment comment) {
        // 设置默认值(可选)
        if (comment.getLikenum() == null) {
            comment.setLikenum(0);
        }
        if (comment.getReplynum() == null) {
            comment.setReplynum(0);
        }
        if (comment.getState() == null) {
            comment.setState("active");
        }

        commentRepository.save(comment);
    }

    // 更新评论
    public void updateComment(Comment comment) {
        commentRepository.save(comment);
    }

    // 根据 ID 删除评论
    public void deleteCommentById(String id) {
        commentRepository.deleteById(id);
    }

    // 查询所有评论
    public List<Comment> findCommentList() {
        return commentRepository.findAll();
    }

    // 根据 ID 查询评论
    public Comment findCommentById(String id) {
        return commentRepository.findById(id).orElseThrow(() ->
                new RuntimeException("评论不存在,ID: " + id)
        );
    }
}

8 测试类

@SpringBootTest
public class CommentServiceTest {
    @Autowired
    private CommentService commentService;
    // 查所有
    @Test
    public void testFindCommentList() {
        List<Comment> commentList = commentService.findCommentList();
        System.out.println(commentList);
    }
    // 插入一个
	@Test
    public void testSaveComment() {
        // 创建一个评论对象
        Comment comment = new Comment();
        // 若不指定ID 则会自动生成
        comment.setArticleid("100000"); // 关联的文章 ID
        comment.setContent("齐夏这波操作简直6到飞起,不愧是「回响」界的扛把子!"); // 评论内容
        comment.setCreatedatetime(LocalDateTime.now()); // 当前时间
        comment.setUserid("1003"); // 用户 ID
        comment.setNickname("齐夏的小迷弟"); // 用户昵称
        comment.setState("1"); // 状态:1 表示正常
        comment.setLikenum(42); // 点赞数(有趣的数字)
        comment.setReplynum(8); // 回复数
        comment.setParentid(null); // 父评论 ID(null 表示顶级评论)
 
        // 保存评论
        commentService.saveComment(comment);
        System.out.println("评论保存成功!");
    }
}
[Comment(id=685a3f60576e6446ef6c4bd0, content=齐夏这波操作简直6到飞起,不愧是「回响」界的扛把子!, publishtime=Tue Jun 24 19:27:27 GMT+08:00 2025, userid=1001, nickname=齐夏的小迷弟, createdatetime=2025-06-24T19:27:27.260, likenum=42, replynum=8, state=1, parentid=null, articleid=100000), 
Comment(id=685a3f60576e6446ef6c4bd1, content=乔家劲大佬又双叒叕carry全场,这波「天龙」直接封神!, publishtime=Tue Jun 24 19:27:28 GMT+08:00 2025, userid=1002, nickname=劲哥的狗腿子, createdatetime=2025-06-24T19:27:28.260, likenum=66, replynum=12, state=1, parentid=null, articleid=100001), 
Comment(id=685a3f60576e6446ef6c4bd2, content=林檎小姐姐的「回响」太绝了,直接把BOSS秀到头皮发麻!, publishtime=Tue Jun 24 19:27:29 GMT+08:00 2025, userid=1003, nickname=檎檎的舔狗, createdatetime=2025-06-24T19:27:29.260, likenum=33, replynum=5, state=1, parentid=null, articleid=100002), 
Comment(id=685a3f60576e6446ef6c4bd3, content=陈俊南这波嘴炮输出直接拉满,BOSS都被他说得怀疑人生了!, publishtime=Tue Jun 24 19:27:30 GMT+08:00 2025, userid=1004, nickname=南哥的捧哏, createdatetime=2025-06-24T19:27:30.260, likenum=55, replynum=10, state=1, parentid=null, articleid=100003), 
Comment(id=685a3f60576e6446ef6c4bd4, content=程雪的「回响」太治愈了,直接把队友从残血奶到满血!, publishtime=Tue Jun 24 19:27:31 GMT+08:00 2025, userid=1005, nickname=雪姐的迷妹, createdatetime=2025-06-24T19:27:31.260, likenum=28, replynum=4, state=1, parentid=10086, articleid=100004)]

评论保存成功!

二 评论分页列表查询

1 更新接口

// 通过上级id`parentid`进行查询分页
public interface CommentRepository extends MongoRepository<Comment, String> {
    // 自定义的分页查询方法 返回 Page<Comment>,表示分页结果(包含数据、页码、总页数等信息)。
    // String parentid:父评论的 ID(null 表示顶级评论)。
    // Pageable pageable:分页参数(如页码、每页大小、排序等)。
    // 方法名需要与实体类属性名相对应(有固定的命名格式)
    Page<Comment> findByParentid(String parentid, Pageable pageable);
}

2 更新 Service 方法

@Service
public class CommentService {
    public Page<Comment> findCommentListByParentid(String parentid, int page, int size) {
        // page 为当前页码 size 为每页包含多少条数据
        // Page从0开始计数 第1页实际上是第0页 因此需要 page - 1
        return commentRepository.findByParentid(parentid, PageRequest.of(page - 1, size));
    }
}

3 更新测试方法

@SpringBootTest
public class CommentServiceTest {
	@Test
    public void testFindCommentListByParentid() {
        // 调用分页查询方法
        Page<Comment> page = commentService.findCommentListByParentid("10086", 1, 3);

        // 输出分页信息
        System.out.println("总记录数: " + page.getTotalElements());
        System.out.println("当前页数据: " + page.getContent());
    }
 }

4 分页查询结果

总记录数: 1
当前页数据: [Comment(id=685a3f60576e6446ef6c4bd4, content=程雪的「回响」太治愈了,直接把队友从残血奶到满血!, publishtime=Tue Jun 24 19:27:31 GMT+08:00 2025, userid=1005, nickname=雪姐的迷妹, createdatetime=2025-06-24T19:27:31.260, likenum=28, replynum=4, state=1, parentid=10086, articleid=100004)]

三 实现评论点赞

1 更新Service方法 – 注入 MongoTemplate

@Service
public class CommentService {
	// Spring Data MongoDB 提供的核心类,用于直接操作 MongoDB 数据库。
	// 它封装了 MongoDB 的 CRUD 操作(如查询、插入、更新、删除),并提供了丰富的 API。
    @Autowired
    private MongoTemplate mongoTemplate;
    
	public void updateCommentLikenum(String id) {
    // 查询条件 创建一个查询对象,条件是 _id 字段等于传入的 id (条件可替换成其他字段)
    // Spring Data MongoDB 提供的查询条件构建方式,可多个条件并列使用
    Query query = Query.query(Criteria.where("_id").is(id));
    
    // 更新条件 创建一个更新操作对象 使用 $inc 操作符将 likenum 字段的值加 1。
    Update update = new Update();
    update.inc("likenum", 1); // 使用 $inc 操作符递增字段值
    
    // 执行更新操作 更新匹配到的第一条记录。 query:查询条件
    // update:更新操作。Comment.class:实体类类型,用于指定操作的集合(comments)
    mongoTemplate.updateFirst(query, update, Comment.class);
	}
}

2 更新测试方法

@Test
public void testUpdateCommentLikenum() {
    String commentId = "1"; // 假设评论 ID 为 "1"
    commentService.updateCommentLikenum(commentId);
}

网站公告

今日签到

点亮在社区的每一天
去签到