SpringBoot整合SpringData MongoDB
1.创建工程并引入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> </dependencies>
2.创建application.yml
spring: #数据源配置 data: mongodb: #主机地址 host: 192.168.43.182 #数据库 database: articledb #默认端口是27017 port: 27017 #也可以使用uri连接 #uri: mongodb://192.168.43.182:27017/articledb #如果数据库需要密码认证 #uri: mongodb://bobo:123456@192.168.43.182:27017/articledb
3.创建启动类
@SpringBootApplication
public class ArticleApplication {
public static void main(String[] args) {
SpringApplication.run(ArticleApplication.class, args);
}
}
4.启动项目,看是否能正常启动,控制台没有错误
5.文章评论实体类的编写
/** * 文章评论实体类 */ @Document(collection = "comment")// 可以省略,如果省略,则默认使用类名小写映射集合 // 复合索引 // @CompoundIndex( def = "{'userid': 1, 'nickname': -1}") public class Comment implements Serializable { //主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写 @Id private String id; // 主键 //该属性对应mongodb的字段的名字,如果一致,则无需该注解 @Field("content") 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 private String articleid; // 文章id /********************* get/set方法 *********************/ }
说明:
索引可以大大提升查询效率,一般在查询字段上添加索引,索引的添加可以通过Mongo的命令来添加,也可以在Java的实体类中通过注解添加。
1)单字段索引注解@Indexed
声明该字段需要索引,建索引可以大大的提高查询效率。
Mongo命令参考:db.comment.createIndex({"userid":1})
2 )复合索引注解@CompoundIndex
复合索引的声明,建复合索引可以有效地提高多字段的查询效率。
Mongo命令参考:db.comment.createIndex({"userid":1,"nickname":-1})
6.创建数据访问接口
/** * 评论的持久层接口 */ public interface CommentDao extends MongoRepository<Comment, String> { }
7.创建业务逻辑类
/** * 评论的业务层 */ @Service public class CommentService { @Autowired private CommentDao commentDao; /** * 保存一个评论 * @param comment */ public void saveComment(Comment comment) { //如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键 commentDao.save(comment); } /** * 更新评论 * @param comment */ public void updateComment(Comment comment) { commentDao.save(comment); } /** * 根据id删除评论 * @param id */ public void deleteCommentById(String id) { commentDao.deleteById(id); } /** * 查询所有评论 * @return */ public List<Comment> findCommentList() { return commentDao.findAll(); } /** * 根据id查询评论 * @param id * @return */ public Comment findCommentById(String id) { return commentDao.findById(id).get(); } }
8.测试
@RunWith(SpringRunner.class) @SpringBootTest(classes = ArticleApplication.class) public class CommentServiceTest { @Autowired private CommentService commentService; /** * 保存一个评论 */ @Test public void testSaveComment() { Comment comment = new Comment(); comment.setArticleid("100000"); comment.setContent("测试添加的数据"); comment.setCreatedatetime(LocalDateTime.now()); comment.setUserid("1003"); comment.setNickname("凯撒大帝"); comment.setState("1"); comment.setLikenum(0); comment.setReplynum(0); commentService.saveComment(comment); } /** * 查询所有数据 */ @Test public void testFindAll() { List<Comment> list = commentService.findCommentList(); System.out.println(list); } /** * 测试根据id查询 */ @Test public void testFindCommentById() { Comment comment = commentService.findCommentById("1"); System.out.println(comment); } }
MongoTemplate 实现评论点赞
低效率的点赞代码: CommentService 新增 updateThumbup方法
/** * 点赞-效率低 * @param id */ public void updateCommentThumbupToIncrementingOld(String id){ Comment comment = commentDao.findById(id).get(); comment.setLikenum(comment.getLikenum() + 1); commentDao.save(comment); }
以上方法虽然实现起来比较简单,但是执行效率并不高,因为我们只需要将点赞数加 1 就可以了,没必要查询出所有字段修改后再更新所有字段。(蝴蝶效应)
可以使用MongoTemplate类来实现对某列的操作。
(1)修改CommentService
//注入MongoTemplate @Autowired private MongoTemplate mongoTemplate;
/** * 赞数+1 * @param id * */ public void updateCommentLikenum(String id) { // 查询对象 Query query = Query.query(Criteria.where("_id").is(id)); // 更新对象 Update update = new Update(); //局部更新,相当于$set // update.set(key,value) // 递增$inc // update.inc("likenum",1); update.inc("likenum"); // 参数1:查询对象 // 参数2:更新对象 // 参数3:集合的名字或实体类的类型Comment.class // mongoTemplate.updateFirst(query, update, "comment"); mongoTemplate.updateFirst(query, update, Comment.class); }
(2)测试
/** * 点赞数+1 */ @Test public void testUpdateCommentLikenum() { //对3号文档的点赞数+1 commentService.updateCommentLikenum("3"); }
SpringDataMongoDB 连接副本集
副本集语法:
mongodb://host1,host2,host3/articledb?connect=replicaSet&slaveOk=true&replicaSet=副本集名字
slaveOk=true :开启副本节点读的功能,可实现读写分离。
connect=replicaSet :自动到副本集中选择读写的主机。如果slaveOK是打开的,则实现了读写分离
修改配置文件application.yml:
spring: #数据源配置 data: mongodb: #主机地址 #host: 192.168.43.182 #数据库 #database: articledb #默认端口是27017 #port: 27017 #副本集的连接字符串 uri: mongodb://192.168.43.182:27017,192.168.43.182:27018,192.168.43.182:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
注意:主机必须是副本集中所有的主机,包括主节点、副本节点、仲裁节点。
完整的连接字符串的参考:
MongoDB客户端连接语法
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
mongodb:// 这是固定的格式,必须要指定。
username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登陆这个数据库
host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接副本集,请指定多个主机地址。
portX 可选的指定端口,如果不填,默认为27017
/database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开test 数据库。
?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开
选项(options):
SpringDataMongDB 连接分片集群:
其连接的是mongs路由,配置和单机mongod的配置是一样的。
多个路由的时候的SpringDataMongoDB的客户端配置参考如下:
spring: #数据源配置 data: mongodb: #主机地址 #host: 192.168.43.182 #数据库 #database: articledb #默认端口是27017 #port: 27017 #副本集的连接字符串 #uri: mongodb://192.168.43.182:27017,192.168.43.182:27018,192.168.43.182:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs #连接路由字符串 uri: mongodb://192.168.43.182:27017,192.168.43.182:27117/articledb