本文共 7784 字,大约阅读时间需要 25 分钟。
SpringBoot是常用开发框架,而MongoDB也是最近越来越火的非关系型数据库,这里使用SpringBoot+MongoDB实现一个小案例,当然MongoDB实际做缓存的可能不多,但是这里仅仅为了一个小demo简单的学习使用,入门上手为目的,更多的复杂查询还需关注MongoDB官网。
如果本篇对你有帮助,还请点赞支持一下!原创作者:
bigsai
如果对MongoDB不太了解,还请先看上篇。
打开Studio 3T数据库管理工具,连接本地MongoDB数据库之后,创建名为test的数据库,在test数据库中创建名为news得集合:
首先,打开IDEA创建项目,选择创建Springboot项目:
然后在选择Gruop和Aritifact时候分别填写com和mongodemo,Java Version选择8版本。在勾选模块时候,这里勾选Spring web、MongoDB依赖模块,选择合适位置创建项目,项目就可以成功创建:
创建完项目,我们需要做一些预备工作用来完成缓存。我们首先要在项目中的application.properties中添加配置连接到数据库,配置规则为:spring.data.mongodb.uri=mongodb://地址:端口/数据库名
,本案例使用本地的MongoDB数据库,默认端口为27017,而使用的MongoDB具体数据库名称为test,那么就可以按照以下进行配置:
spring.data.mongodb.uri=mongodb://localhost:27017/test
这样在项目中就可以连接到本地的MongoDB的test数据库并访问。
其次在项目中com.mongodb目录下分别创建controller,service,pojo文件夹,在controller文件夹下创建newsController.java
类,为负责url和逻辑的控制器:
package com.mongodemo.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class newsController { private static Logger logger= LoggerFactory.getLogger(newsController.class); }
其中:
controller创建完毕在service 文件夹下创建NewsService.java
类,里面先编写以下内容:
package com.mongodemo.service;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.stereotype.Service;@Servicepublic class NewsService { private static Logger logger= LoggerFactory.getLogger(NewsService.class); @Autowired MongoTemplate mongoTemplate; }
其中:
service创建完成,我们需要在pojo中创建news类,代表新闻实体内容。
import java.util.Date;public class news { private String title; private Date date; private String brief; private String content; private String author; @Override public String toString() { return "news{" + "title='" + title + '\'' + ", date=" + date + ", brief='" + brief + '\'' + ", content='" + content + '\'' + ", author='" + author + '\'' + '}'; } public news(String title, Date date, String brief, String content, String author) { this.title = title; this.date = date; this.brief = brief; this.content = content; this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getBrief() { return brief; } public void setBrief(String brief) { this.brief = brief; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; }}
其中各个字段分别表示为:
名称 | 含义 |
---|---|
title | 标题 |
date | 日期 |
brief | 概要 |
content | 内容 |
author | 作者 |
下面开始实战MongoDB实现一个新闻得缓存功能,实现缓存之前,要清楚缓存的核心作用:提升web程序的查询速度,将热点数据放到非关系数据库中。本案例对接口进行缓存,不过真正的缓存实例需要考虑很多问题比如时效性,缓存那些数据等。在这里主要为了讲解MongoDB的一个实例。
在查询时候,缓存和数据库之间通常是这么配合的:
为了降低整个项目的复杂度,这里用手动生成的数据对象代替成数据库中查询的数据,我们在NewsService中编写getNewsByTitle(String title)函数,其功能是根据标题返回缓存或数据库中该条news数据,如果MongoDB中存在则直接返回该对象,否则先从数据库查询(这里直接生成),然后存到MongoDB中再返回。具体代码为:
public news getNewsByTitle(String title) { //查询数据先从MongoDB中查询 Query query = new Query(Criteria.where("title").is(title)); news news=mongoTemplate.findOne(query, news.class); if(news==null)//缓存中没该条记录 { logger.info("从数据库查询数据"); //假设news1从数据库中查询 news news1=new news(title,new Date(),"","","bigsai"); news1.setBrief("有了博学谷,妈妈再也不用担心我的java学习!"); news1.setContent("博学谷优质学习资料为java学习提供更好环境,越来越多开发者学习使用"); mongoTemplate.insert(news1,"news"); logger.info("数据插入到MongoDB成功"); news=news1; } else { logger.info("数据从缓存访问成功"); } return news; }
上面的代码中:
在newsController中,我们编写一个名称为getnews的接口,用来给用户返回该标题新闻(news类)的一条数据的JSON文件,具体代码为:
@Autowired NewsService newsService; @GetMapping("getnews/{title}") public news getnews(@PathVariable String title) { news news=newsService.getNewsByTitle(title); return news; }
上面代码中:
我们启动程序,浏览器输入localhost:8080/getnews/好好学java
页面会有返回的结果,返回的一个news对象序列化成JSON的字符串的文本。
同时,你查看IDEA的日志,由于第一次查询,MongoDB中没有对应数据你会发现会先从数据库中查询然后存储到MongoDB中:
查看MongoDB的news集合发现记录被成功插入了,多刷新页面localhost:8080/getnews/好好学java
你会发现数据会直接从MongoDB中返回: 缓存中的数据和存储的关系数据库的数据是一致的,当我们只有查询操作的时候,可以一直保持数据的一致性,但是我们如果对数据有更新、删除的操作,就需要对关系数据库和MongoDB中的数据同时进行更新或删除的操作,让数据再次达到一致性的效果。
虽然大部分情况我们对热点新闻数据可能很少更新,但是也有时候新闻中有部分内容需要更改的需要我们完成,比如比分错字或者不妥的言论。
我们在NewsService中编写updateNewsContentByTitle((String title,String content)函数,其作用为更新数据库(这里没有具体实现)和MongoDB缓存中的数据:
public boolean updateNewsContentByTitle(String title,String content) { try { Query query = new Query(Criteria.where("title").is(title)); Update update = new Update(); update.set("content", content);//更新内容 update.set("date",new Date());//更新时间 // 假设在这里数据库中更新过这里跳过 // updateFirst 更新查询返回结果集的第一条 //upsert 更新如果不存在就插入 mongoTemplate.upsert(query, update, news.class); } catch (Exception e) { return false; } return true; }
其中:
编写完service,在newsController中编写一个名为updatenews的接口,用来更新数据库数据和缓存在MongoDB的数据:
@GetMapping("updatenews") public String updatenews(String title,String content) { boolean bool=newsService.updateNewsContentByTitle(title,content); if(bool) return "更新成功"; else return "更新失败"; }
启动程序访问localhost:8080/updatenews?title=好好学java&content=学好java走遍全天下
,你会发现数据更新成功:
除了更新的时候需要保证数据一致性,删除的时候也需要保证数据一致性,如果在删除关系数据库的数据而不删除MongoDB缓存,那么下次查询该条数据MongoDB中存在而关系数据库中不存在,这样就造成了数据不一致,所以在删除数据的时候我们需要在MongoDB中的数据也删除。
在NewsService中编写deleteNewsByTitle(String title)函数,用来根据标题title删除MongoDB中的记录:
public boolean deleteNewsByTitle(String title) { try { Query query = new Query(Criteria.where("title").is(title)); mongoTemplate.remove(query,news.class); } catch (Exception e) { return false; } return true; }
mongoTemplate.remove(query,news.class);意味从MongoDB中删除满足查询条件的记录。其中query为查询条件,news.class为删除对象在Java中的类。
在newsController中编写deletenews接口,用来处理删除的请求:
@GetMapping("deletenews/{title}") public String deletenews(@PathVariable String title) { try { newsService.deleteNewsByTitle("好好学java"); return "删除成功"; } catch (Exception e) { return "删除失败"; } }
启动程序,访问http://localhost:8080/deletenews/好好学java
,会发现缓存在MongoDB中的记录被成功删除,这样就保证MongoDB中不会出现关系数据库中不存在的脏数据,达到数据一致性!
本篇到这里就结束了,如果帮助还请不要吝啬你的小赞、收藏一份如有更多期待还请关注公众号bigsai
,回复bigsai获取珍藏pdf资源一份!
转载地址:http://jvvkz.baihongyu.com/