redis
NOSQL
什么是NOSQL
NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”
是一项全新的数据库理念,泛指非关系型的数据库。
NOSQL解决什么问题
web程序不再仅仅专注在功能上,同时也在追求性能
High performance --- 对数据库高并发读写的需求
现在数据库并发负载非常高,往往要达到每秒上万次读写请求
关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了
Huge Storage --- 对海量数据的高效率存储和访问的需求
对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的
High Scalability && High Availability --- 对数据库的高可扩展性和高可用性的需求
对于很多需要提供24小时不间断服务的网站来说,
对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移
主流的NOSQL产品
主流产品
键值(Key-Value)存储数据库-redis
- 主要使用内存, 有两种持久化方案, 速度非常快,
- 一般做分布式缓存使用
文档型数据库-MongoDB
- 主要使用硬盘存储, 所以不会担心数据丢失, 速度介于redis和传统数据库之间.
- 但是mongodb更擅长存储大文本数据, 以及一些非结构化数据,
- mongodb比redis的数据类型更加丰富.
- 例如: 存储小说网站的小说, 存储电商网站的评论等这些数据
redis概述
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库
官方提供测试数据
50个并发执行100000个请求
读的速度是110000次/s
写的速度是81000次/s
redis的应用场景
缓存(数据查询、短连接、新闻内容、商品内容等等)
聊天室的在线好友列表
任务队列。(秒杀、抢购、12306等等)
应用排行榜
网站访问统计
数据过期处理(可以精确到毫秒
分布式集群架构中的session分离
业务流程
获取数据的时候先从redis中获取, 如果获取到数据则直接返回, 就不用访问数据库了
如果获取不到数据, 可以从数据库中查询, 查询到后放入redis中一份, 下回就可以直接从redis中查询到
这样大大降低了数据库的高并发访问压力。
持久化方案
RDB(默认) 分时持久化
可以在配置文件中设定, 多长时间持久化一次, 持久化次数少也就是操作硬盘的次数少,
速度快. 但是如果在没有完成持久化前, 如果服务器断电, 则内存中没有持久化的数据会丢失.
AOF 实时持久化
每次向redis中做增删改操作, 都会将数据持久化到硬盘上, 数据可靠性高, 不会丢失,
但是速度慢
redis安装
windows
- window版的安装及其简单,
- 解压Redis压缩包完成即安装完毕
- 双击Redis目录中redis-server.exe可以启动redis服务,Redis服务占用的端口是6379
- 关闭Redis的控制台窗口就可以关闭Redis服务
linux
将redis在Linux的安装包上传到/usr/local当中
cd /usr/local
解压
tar -zxvf redis-4.0.9.tar.gz
rm -rf redis-4.0.9.tar.gz
编译安装
进入到redis目录
cd /usr/local/redis-4.0.9/
make
make install PREFIX=\'/usr/local/redis-4.0.9/6379\'
启动
cd /usr/local/redis-4.0.9/6379/bin
./redis-server
修改配置文件
cd /usr/local/redis-4.0.9/
把/usr/local/redis-4.0.9/目录下的配置文件复制一份到6379目录下
cp redis.conf /usr/local/redis-4.0.9/6379/bin/
修改配置文件
cd /usr/local/redis-4.0.9/6379/bin/
#bind 127.0.0.1 # 将这行代码注释,监听所有的ip地址,外网可以访问
protected-mode no # 把yes改成no,允许外网访问
daemonize yes # 把no改成yes,后台运行
重新启动
./redis-server redis.conf
ps -ef|grep redis
Redis的数据类型
概述
- redis是一种高级的key-value的存储系统,其中value支持五种数据类型
Redis的5种数据类型
- 字符串(String)
- 哈希(hash)
- 字符串列表(list)
- 字符串集合(set)
- 序字符串集合(sorted set)
key的定义注意点
- key不要太长,最好不要操作1024个字节,这不仅会消耗内存还会降低查找效率
- key不要太短,如果太短会降低key的可读性
- 在项目中,key最好有一个统一的命名规范
基本操作
字符串类型string
概述
- 设定key持有指定的字符串value,如果该key存在则进行覆盖操作。总是返回”OK”
操作
set key value
set name gaowei
get key
获取key的value。如果与该key关联的value不是String类型,redis将返回错误信息,
get name
del key
del name
删除后,返回整数1,表示删除成功
哈希类型hash
概述
- Redis中的Hash类型可以看成具有String Key和String Value的map容器
- 所以该类型非常适合于存储值对象的信息
操作
hset key field value
为指定的key设定field/value对(键值对)
hset myhash username gaowei
存入hash类型值 myhast存的值为username:gaowei
hget key field
返回指定的key中的field的值
hset myhash username
返回值为gaowei
hdel key field [field … ]
可以删除一个或多个字段,返回值是被删除的字段个数
hdel myhash username
hdel myhash password
hgetall key
可以获取该键的所有数据
hgetall myhash
列表类型list
概述
- 在Redis中,List类型是按照插入顺序排序的字符串链表。
- 和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素
- 在插入时,如果该键并不存在,Redis将为该键创建一个新的链表
- 与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除
- List中可以包含的最大元素数量是4294967295
操作
lpush key values[value1 value2…]
在指定的key所关联的list的头部插入所有的values,
如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。
插入成功,返回元素的个数
lpush mylist a b c
lpop key
返回并弹出指定的key关联的链表中的第一个元素,即头部元素
如果该key不存在,返回nil;
若key存在,则返回链表的头部元素。
lpop mylist
c
lpop mylist
b
rpop key
从尾部弹出元素。
lpush mylist a b c
rpop mylist
a
lrange key
遍历该键的所有数据
lrange key 0 2
返回0 1 2
lrange key 0 -1
返回所有
集合类型set
概述
- 在Redis中,我们可以将Set类型看作为没有排序的字符集合
- 和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作
- Set集合中不允许出现重复的元素。
操作
sadd key values[value1、value2…]
向set中添加数据,如果该key的值已有则不会重复添加
sadd myset a b c
smembers key
获取set中所有的成员
smembers myset
srem key members[member1、member2…]
删除set中指定的成员
srem myset a b
有序集合类型sortset
概述
- 在redis中,可以保证不重复的元素,仍然可以进行排序
操作
zadd key values[value1、value2…]
zadd mysort 5 zs 10 lisi 7 wc 8 xk
zrange key 索引 索引
zrange mysort 0 -1
zrem key value
zrem mysort lisi
Redis的通用命令
keys pattern
获取所有与pattern匹配的key,返回所有与该key匹配的keys。
*表示任意一个或多个字符,?表示任意一个字符
keys *
del key1 key2…
删除指定的key
del myset
exists key
判断该key是否存在,1代表存在,0代表不存在
exists mysort
type key
获取指定key的类型。该命令将以字符串的格式返回
返回的字符串为string、list、set、hash,如果key不存在返回none
type mysort
Redis的持久化
概述
- Redis的高性能是由于其将所有数据都存储在了内存中
- 为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中同步到硬盘中,这一过程就是持久化
- Redis支持两种方式的持久化,可以单独使用其中一种或将二者结合使用。
一种是RDB方式,一种是AOF方式。
RDB持久化(默认支持,无需配置)
该机制是指在 指定的时间间隔 内将内存中的数据集快照写入磁盘。
AOF持久化
该机制将以日志的形式记录服务器所处理的每一个写操作
在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。
无持久化
我们可以通过配置的方式禁用Redis服务器的持久化功能
这样我们就可以将Redis视为一个功能加强版的memcached了
redis可以同时使用RDB和AOF
RDB持久化机制
RDB持久化机制优点
一旦采用该方式,那么你的整个Redis数据库将只包含一个文件
这对于文件备份而言是非常完美的
RDB持久化机制缺点
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
快照触发条件
客户端执行命令save和bgsave会生成快照;
根据配置文件save m n规则进行自动快照;
主从复制时,从库全量复制同步主库数据,此时主库会执行bgsave命令进行快照;
客户端执行数据库清空命令FLUSHALL时候,触发快照;
客户端执行shutdown关闭redis时,触发快照;
RDB持久化机制的配置
save m n
配置快照(rdb)促发规则,格式:save <seconds> <changes>
save 900 1 900秒内至少有1个key被改变则做一次快照
save 300 10 300秒内至少有10个key被改变则做一次快照
save 60 10000 60秒内至少有10000个key被改变则做一次快照
#关闭该规则使用save “ ”
dbfilename dump.rdb
rdb持久化存储数据库文件名,默认为dump.rdb
stop-write-on-bgsave-error yes
yes代表当使用bgsave命令持久化出错时候停止写RDB快照文件,no表明忽略错误继续写文件。
rdbchecksum yes
在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
dir "./"
数据文件存放目录,rdb快照文件和aof文件都会存放至该目录,请确保有写权限
rdbcompression yes
是否开启RDB文件压缩,该功能可以节约磁盘空间
AOF持久化机制
AOF概述
- 当redis存储非临时数据时,为了降低redis故障而引起的数据丢失,redis提供了AOF(Append Only File)持久化,
- 从单词意思讲,将命令追加到文件。AOF可以将Redis执行的每一条写命令追加到磁盘文件(appendonly.aof)中
- 在redis启动时候优先选择从AOF文件恢复数据。由于每一次的写操作,redis都会记录到文件中,所以开启AOF持久化会对性能有一定的影响
- AOF持久化数据丢失更少,其消耗内存更少(RDB方式执行bgsve会有内存拷贝)
开启AOF持久化
- 默认情况下,redis是关闭了AOF持久化,开启AOF通过配置appendonly为yes开启
- 将appendonly修改为yes,开启aof持久化机制,默认会在目录下产生一个appendonly.aof文件
- 我们修改配置文件或者在命令行直接使用config set修改,再用config rewrite同步到配置文件。
- 通过客户端修改好处是不用重启redis,AOF持久化直接生效
/usr/local/redis-4.0.9/6379/bin
./redis-cli
config get appendonly
查询配置状态
config set appendonly yes
修改配置
config rewrite
写入到redis.conf中,使配置生效
开启后,在/usr/local/redis-4.0.9/6379/bin目录下,会生成appendonly.aof文件
配置
在redis.conf配置文件中修改
appendfsync
always
每执行一次更新命令,持久化一次
appendfsync
everysec
每秒钟持久化一次
appendfsync
no
不持久化
RDB-AOF混合持久化
- 通过aof-use-rdb-preamble配置参数控制,yes则表示开启,no表示禁用,默认是禁用的,可通过config set修改。
密码设置
- redis没有实现访问控制这个功能,但是它提供了个轻量级的认证方式, 可以编辑redis. conf配置来启用认证。
cd /usr/local/redis-4.0.9/6379/bin
./redis-cli
查看密码
config get requirepass
初始化Redis密码:
requirepass这个就是配置redis文件访问密码的参数
vi /usr/local/redis-4.0.9/6379/bin/redis.conf
修改对应参数
requirepass 123456
需重启Redis才能生效
不重启Redis设置密码
config set requirepass 123456
config rewrite
验证
auth 123456
jedis的介绍
使用Jedis操作redis需要导入jar包如下:
commons-pool2-2.3.jar
jedis-2.7.0.jar
jedis常用API
new Jedis(host, port)
创建jedis对象,参数host是redis服务器地址,参数port是redis服务端口
set(key,value)
设置字符串类型的数据
get(key)
获得字符串类型的数据
hset(key,field,value)
设置哈希类型的数据
hget(key,field)
获得哈希类型的数据
lpush(key,values)
设置列表类型的数据
lpop(key)
列表左面弹栈
rpop(key)
列表右面弹栈
del(key)
删除指定的key
jedis的基本操作
public void testJedis(){
//1 设置ip地址和端口
Jedis jedis = new Jedis("localhost", 6379);
//2 设置数据
jedis.set("name", "fmjava");
//3 获得数据
String name = jedis.get("name");
System.out.println(name);
//4 释放资源
jedis.close();
}
jedis连接池的基本概念
- jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的池化技术
示例代码
public void testJedisPool(){
//1 获得连接池配置对象,设置配置项
JedisPoolConfig config = new JedisPoolConfig();
// 1.1 最大连接数
config.setMaxTotal(30);
// 1.2 最大空闲连接数
config.setMaxIdle(10);
//2 获得连接池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
//3 获得核心对象
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4 设置数据
jedis.set("name", "fmjava");
//5 获得数据
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
// 虚拟机关闭时,释放pool资源
if(jedisPool != null){
jedisPool.close();
}
}
}
SpringDataRedis
概述
- Spring-data-redis是spring大家族的一部分
- 提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装
- RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅
spring-data-redis功能
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
ValueOperations:简单K-V操作
Spring Data Redis入门程序
1.构建Maven工程 SpringDataRedisDemo jar工程
2.引入Spring/Jedis和SpringDataRedis依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
</dependencies>
4.在src/main/resources建立redis-config.properties
redis.host=192.168.1.88
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
5.在src/main/resources创建applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:*.properties" />
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>
6.建立TestString测试字符串操作方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSet() {
redisTemplate.boundValueOps("name").set("myxq");
}
@Test
public void testGet() {
String name = (String) redisTemplate.boundValueOps("name").get();
System.out.println("name=" + name);
}
@Test
public void testDelete() {
redisTemplate.delete("name");
}
}
7.建立TestList测试List操作方法
- Lpush
- Rpush
- Range
- testDelete
示例代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestList {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testLpush() {
redisTemplate.boundListOps("myListKey").leftPush("001");
redisTemplate.boundListOps("myListKey").leftPush("002");
redisTemplate.boundListOps("myListKey").leftPush("003");
redisTemplate.boundListOps("myListKey").leftPush("004");
}
@Test
public void testRpush() {
redisTemplate.boundListOps("myListKey").rightPush("001");
redisTemplate.boundListOps("myListKey").rightPush("002");
redisTemplate.boundListOps("myListKey").rightPush("003");
redisTemplate.boundListOps("myListKey").rightPush("004");
}
@Test
public void testRange() {
List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
for (String s : myListKey) {
System.out.println("value=" + s);
}
}
@Test
public void testDelete() {
redisTemplate.delete("myListKey");
}
}
8.建立TestHash测试hash
- hash格式
- Put
- Get
- entries
- delete
示例代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestHash {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testPut() {
redisTemplate.boundHashOps("keyname1").put("name", "zs");
redisTemplate.boundHashOps("keyname1").put("age", "20");
redisTemplate.boundHashOps("keyname1").put("phone", "121");
redisTemplate.boundHashOps("keyname1").put("email", "1@qq.com");
}
@Test
public void testGetOne() {
String name = (String)redisTemplate.boundHashOps("keyname1").get("name");
System.out.println("name =" + name);
}
@Test
public void testGetAll() {
//获取所有的entries
Map<String, String> testHash = (Map<String, String>)redisTemplate.boundHashOps("keyname1").entries();
Set<Map.Entry<String, String>> entries = testHash.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key=" + entry.getKey());
System.out.println("value=" + entry.getValue());
}
}
@Test
public void testDeleteOne() {
redisTemplate.boundHashOps("keyname1").delete("name");
}
@Test
public void testDeleteAll() {
redisTemplate.delete("keyname1");
}
}
使用redis缓存广告
在common工程的pom文件当中添加redis依赖
<!-- Jackson Json处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
在common工程当中添加redis配置文件和属性文件
properties/redis-config.properties
redis.host=192.168.1.88
redis.port=6379
redis.pass=123456
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
spring/applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:/properties/*.properties" />
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>
使用redis过程分析
- 获取数据的时候先从redis中获取, 如果获取到数据则直接返回, 就不用访问数据库了
- 如果获取不到数据, 可以从数据库中查询, 查询到后放入redis中一份, 下回就可以直接从redis中查询到
- 这样大大降低了数据库的高并发访问压力.
查询分类广告方法
- 在Common工程当中创建工具类统一管理 redis键
public class Constants {
public static final String CONTENT_LIST_REDIS = "content";
}
- redis数据存在结构
- field为分类名称,value为分类下的广告
创建从redis中取广告分类方法
@Override
public List<Content> findByCategoryIdFromRedis(Long categoryId) {
//1. 首先根据分类id到redis中获取数据
List<Content> contentList = (List<Content>)redisTemplate
.boundHashOps(Constants.CONTENT_LIST_REDIS)
.get(categoryId);
//2. 如果redis中没有数据则到数据库中获取数据
if (contentList == null) {
//3. 如果数据库中获取到数据, 则放入redis中一份
contentList = findByCategoryId(categoryId);
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).put(categoryId, contentList);
}
return contentList;
}
添加广告方法
@Override
public void add(Content content) {
//1. 将新广告添加到数据库中
contentDao.insertSelective(content);
//2. 根据分类id, 到redis中删除对应分类的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
}
删除
@Override
public void delete(Long[] ids) {
if (ids != null) {
for (Long id : ids) {
//1. 根据广告id, 到数据库中查询广告对象
Content content = contentDao.selectByPrimaryKey(id);
//2. 根据广告对象中的分类id, 删除redis中对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
//3. 根据广告id删除数据库中的广告数据
contentDao.deleteByPrimaryKey(id);
}
}
}
更新
@Override
public void update(Content content) {
//1. 根据广告id, 到数据库中查询原来的广告对象
Content oldContent = contentDao.selectByPrimaryKey(content.getId());
//2. 根据原来的广告对象中的分类id, 到redis中删除对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(oldContent.getCategoryId());
//3. 根据传入的最新的广告对象中的分类id, 删除redis中对应的广告集合数据
redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).delete(content.getCategoryId());
//4. 将新的广告对象更新到数据库中
contentDao.updateByPrimaryKeySelective(content);
}