Springboot+mysql+mybatis+druid+redis实现数据库缓存实战

首先我们需要引入依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.0.1</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-redis</artifactId>
		    <version>2.1.6.RELEASE</version>
		</dependency>
		<dependency>
		    <groupId>org.mybatis.spring.boot</groupId>
		    <artifactId>mybatis-spring-boot-starter</artifactId>
		    <version>2.0.0</version>
		</dependency>
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>fastjson</artifactId>
		    <version>1.2.57</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.9.2</version>
		</dependency>
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-devtools</artifactId>
		    <scope>true</scope>
		    </dependency>
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>druid-spring-boot-starter</artifactId>
		    <version>1.1.16</version>
		</dependency>

将上述依赖引入后,我们需要编写配置文件

#服务启动的端口号(用Tomcat运行时无效)
server.port=8082
#项目的部署名称(用Tomcat运行时无效)
server.servlet.context-path=/SpringTemplate

#数据库相关配置
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=jack
spring.datasource.password=liuhong987
#如果不使用默认的数据库连接池 (com.zaxxer.hikari.HikariDataSource)
spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#配置druid连接池时用一下配置
spring.datasource.druid.initial-size=10
spring.datasource.druid.max-active=50
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-wait=60000

#mybatis 下划线转驼峰配置,两者都可以(在执行查询时将查询结果自动转换成对象)
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true
#xml文件存放位置
mybatis.mapper-locations=classpath:com/springboot/mapper/*.xml
#xml对应接口所在包名
mybatis.type-aliases-package=com.springboot.dao
#打印sql,方便调试
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#Redis的主机名
spring.redis.host=127.0.0.1
# 使用的数据库(0-15),默认为0
spring.redis.database=0
#redis服务器密码
spring.redis.password=
#redis的端口号
spring.redis.port=6379 
spring.redis.ssl=false
#Redis连接超时
spring.redis.timeout=2000
spring.redis.jedis.pool.max-active=80
spring.redis.jedis.pool.max-idle=50
spring.redis.jedis.pool.max-wait=200ms
spring.redis.jedis.pool.min-idle=0

将上述步骤完成后,我们就需要开始编写Redis的配置类了

@Configuration
@EnableCaching
public class RedieConfig  extends CachingConfigurerSupport {
	@Bean(name="redisTemplate")
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
		template.setConnectionFactory(factory);
		setSerializer(template);
        return template;
    }
	@Bean(name="redisCacheManager")
    public CacheManager cacheManager(RedisConnectionFactory factory) {
		        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);
		        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
		        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
		        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
		        defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(100));//设置过期时间
		        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
		        ParserConfig.getGlobalInstance().addAccept("zmc.leon.mcd.entity.");
		        ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
		        return cacheManager;
    }
	
	/**
	 * 利用fastjson将转为json字符串
	 * @param template
	 */
	private void setSerializer(RedisTemplate<Object, Object> template) {
        @SuppressWarnings({"rawtypes", "unchecked"})
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer =new FastJsonRedisSerializer<Object>(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
    }
	 /**
     * 自定义生成key的规则
     *
     * @return
     */
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                //格式化缓存key字符串
                StringBuilder sb = new StringBuilder();
                //追加类名
                sb.append(o.getClass().getName()).append(".");
                //追加方法名
                sb.append(method.getName());
                //遍历参数并且追加
                for (Object obj : objects) {
                    sb.append(".");
                    sb.append(obj.toString());
                }
                System.out.println("调用Redis缓存Key : " + sb.toString());
                return sb.toString();
            }
        };
    }
}

注意我们这里使用的是redis的String类型作为缓存,使用fastjson将缓存数据转为json字符串进行缓存。

还要注意一个问题,我们这里必须自定义fastjson的的序列化类。否则会出现异常,下面是自定义的fastjson序列化的类。

在redis的配置类中一定要引入自定义的FastJsonRedisSerializer类,而不是自带的序列化类

public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private Class<T> clazz;
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }
 
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (null == t) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
 
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return (T) JSON.parseObject(str, clazz);
    }
}

到这里, 我们已经基本构建完的Redis的环境,下面我们就要结合mybatis来使用它作为数据库缓存

首先我们来看一下建一个简单表测试下,下面是SQL语句

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(32) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `sex` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10009 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

下面我么使用自动生成代码工具generator来生成xml,实体类文件、以及接口文件

实体类文件

package com.springboot.domain;

public class User {
    private Long id;

    private String username;

    private String sex;

    private Integer age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username == null ? null : username.trim();
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex == null ? null : sex.trim();
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

XML文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.springboot.dao.UserMapper" >
  <resultMap id="BaseResultMap" type="com.springboot.domain.User" >
    <id column="id" property="id" jdbcType="BIGINT" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="sex" property="sex" jdbcType="VARCHAR" />
    <result column="age" property="age" jdbcType="INTEGER" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, username, sex, age
  </sql>
  
  <select id="selectList" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from user
    where 1=1
  </select>
  
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
    select 
    <include refid="Base_Column_List" />
    from user
    where id = #{id,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
    delete from user
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.springboot.domain.User" >
  <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER" >
    SELECT LAST_INSERT_ID()
  </selectKey>
    insert into user (id, username, sex, 
      age)
    values (#{id,jdbcType=BIGINT}, #{username,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, 
      #{age,jdbcType=INTEGER})
  </insert>
  
  <insert id="insertSelective" parameterType="com.springboot.domain.User" >
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="username != null" >
        username,
      </if>
      <if test="sex != null" >
        sex,
      </if>
      <if test="age != null" >
        age,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=BIGINT},
      </if>
      <if test="username != null" >
        #{username,jdbcType=VARCHAR},
      </if>
      <if test="sex != null" >
        #{sex,jdbcType=VARCHAR},
      </if>
      <if test="age != null" >
        #{age,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.springboot.domain.User" >
    update user
    <set >
      <if test="username != null" >
        username = #{username,jdbcType=VARCHAR},
      </if>
      <if test="sex != null" >
        sex = #{sex,jdbcType=VARCHAR},
      </if>
      <if test="age != null" >
        age = #{age,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.springboot.domain.User" >
    update user
    set username = #{username,jdbcType=VARCHAR},
      sex = #{sex,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER}
    where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>

接口类文件

public interface UserMapper {
    int deleteByPrimaryKey(Long id);
    int insert(User record);
    int insertSelective(User record);
    List<User> selectList();
    User selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}

service层文件

@Service
@CacheConfig(cacheNames = "user")
public class UserService {
	@Autowired
	private UserMapper userMapper;
    @Cacheable(key="#id")
	public User findById(String id) {
		// TODO Auto-generated method stub
		return userMapper.selectByPrimaryKey(Long.parseLong(id));
	}
    @Cacheable(key ="'userList'+#accountId")
	public Object selectList(String accountId) {
		// TODO Auto-generated method stub
		return userMapper.selectList();
	}
	@CachePut(key = "#user.id")
	public Object saveUser(User user) {
		// TODO Auto-generated method stub
		return userMapper.insert(user);
	}
	@CachePut(key = "#user.id")
	public Object updateUser(User user) {
		// TODO Auto-generated method stub
		return userMapper.updateByPrimaryKey(user);
	}
	@CacheEvict(key ="#id")
	public Object deleteById(String id) {
		// TODO Auto-generated method stub
		return userMapper.deleteByPrimaryKey(Long.parseLong(id));
	}
}

我们使用redis作为缓存是在service层加注解实现的

@CacheConfig(cacheNames = "user")  这个是我定义缓存的名字,原则上是必须的

@Cacheable(key ="'userList'+#accountId")  这个是在在查询时使用的缓存注解,一定要定义key值,唯一的。

@CachePut(key = "#user.id")  在实现增加和修改功能时使用该缓存注解

 @CachePut(key = "#user.id") 在实现删除功能时,使用该缓存注解

下面我们继续实现controller层

@RestController
@RequestMapping("/user/v1/")
public class UserController {
	@Autowired
	private UserService userService;
	
	@RequestMapping("findById")
	public Object  findById(String id) {
		 return  userService.findById(id);	
	}
	@RequestMapping("list")
	public Object  selectList(String accountId) {
		 return  userService.selectList(accountId);	
	}
	
	@RequestMapping("deleteById")
	public Object  deleteById(String id) {
		 return  userService.deleteById(id);	
	}
	
	@RequestMapping("save")
	public Object  saveUser(@RequestBody User user) {
		 return  userService.saveUser(user);	
	}
	
	@RequestMapping("update")
	public Object  updateUser(@RequestBody User user) {
		 return  userService.updateUser(user);	
	}
}

接下来启动类也是非常关键的

@SpringBootApplication
@MapperScan("com.springboot.dao")
//@EnableCaching   //当redis的配置类里面未开启缓存功能,则此处必须开启此注解。
public class ApplicationBoot {
	public static void main(String[] args) {
		SpringApplication.run(ApplicationBoot.class, args);
		
	}

}

以上过程利用redis实现的数据库简单的数据缓存功能。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值