【SpringBoot】SpringBoot学习笔记——整合数据库


4. SpringBoot整合数据库

4.1 整合Redis缓冲

是一个基于内存的单线程高性能Key-Value型数据库。整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flash到硬盘上进行保存。因为是纯内存操作,Redis性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最高的Key-Value数据库。

Redis可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:string(字符串)、list(列表)、set(集合)、hash(哈希类型)、Sorted Set(有序集合)。

4.1.1 Redis数据库操作

  • 对字符串的操作
  • 对List集合的操作
  • 对set集合的操作
  • 对Hash集合的操作
  • 对zset的操作

参考https://blog.csdn.net/icetime17/article/details/45767559

4.1.2 SpringBoot整合Redis

  • 创建SpringBoot项目

    首先创建Spring Boot Web项目,添加Redis依赖,并添加Redis的缓冲连接池,常用的缓冲连接池为Lettuce和Jedis。Jedis在多线程使用同一个连接时,线程是不安全的,所以要使用连接池,得为每一个Jedis实例分配一个连接。Lettuce在多线程使用统一连接实例时,线程是安全的。Redis默认使用Lettuce连接池,依赖如下:

    <!--Redis相关依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!--Lettuce pool缓冲连接池-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
    
  • 配置文件

    在application.properties中,添加如下配置信息:

    # Redis数据库索引(默认为0)
    spring.redis.database=0  
    # Redis服务器地址
    spring.redis.host=localhost
    # Redis服务器连接端口
    spring.redis.port=6379  
    # Redis服务器连接密码(默认为空)
    spring.redis.password=
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.lettuce.pool.max-active=8  
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.lettuce.pool.max-wait=-1ms
    # 连接池中的最大空闲连接
    spring.redis.lettuce.pool.max-idle=8 
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0  
    
  • 创建实体类

    创建一个City类:

    package com.shenziyi.db.entity;
    
    import java.io.Serializable;
    
    public class City implements Serializable {
        private int id;
        private String name;
        private String country;
    
        public City(int id, String name, String country) {
            this.id = id;
            this.name = name;
            this.country = country;
        }
    
        @Override
        public String toString() {
            return "City{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", country='" + country + '\'' +
                    '}';
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    }
    
  • 创建Controller

    实体类及Redis的连接信息添加完成后,创建一个CityController进行测试:

    package com.shenziyi.db.controller;
    
    import com.shenziyi.db.entity.City;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.web.bind.annotation.GetMapping;
    
    public class CityController {
    
        @Autowired
        private RedisTemplate redisTemplate;
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
        @GetMapping("/")
        public void testRedis(){
            ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
            //添加字符串
            ops.set("name", "beixi");
            String name=ops.get("name");
            System.out.println(name);
            ValueOperations opsForValue = redisTemplate.opsForValue();
            City city=new City(1, "北京", "中国");
            //添加实体类
            opsForValue.set("city", city);
            Boolean exists = redisTemplate.hasKey("city");
            System.out.println("redis是否存在相应的key:"+exists);
            //删除
            redisTemplate.delete("city");
            //更新
            redisTemplate.opsForValue().set("city", new City(2, "山西","中国"));
            //查询
            City c2 = (City) redisTemplate.opsForValue().get("city");
            System.out.println("从redis数据库中获取city:"+c2.toString());
    
        }
    }
    

    RedisTemplate和StringRedisTemplate都是Spring Data Redis为我们提供的模板类,用来对数据进行操作,都通过Spring提供的Serializer序列化到数据库。其中StringRedisTemplate是RedisTemplate的子类,只针对键值都是字符串的数据进行操作,采用的序列化方案是StringRedisSerializer,而RedisTemplate可以操作对象,采用的序列化方案是JdkSerializationRedisSerializer。在SpringBoot中默认提供这两个模板类,RedisTemplate和StringRedisTemplate都提供了Redis的基本操作方法。

    RedisTemplate和StringRedisTemplate还为我们提供了下面几个数据访问方法:

    • opsForList:操作list数据。
    • opsForSet:操作Set数据。
    • opsForZSet:操作ZSet数据。
    • opsForHash:操作Hash数据。
  • 测试:在浏览器中输入http://localhost:8080/访问,观察控制台上打印的日志信息:
    在这里插入图片描述
    也可以使用RedisClient客户端工具查看Redis缓冲数据库中的数据:
    在这里插入图片描述

4.1.3 Redis缓冲在SpringBoot项目中的应用

在开发中,如果以相同的查询条件频繁查询数据库,会给数据库带来很大的压力。因此,我们需要对查询出来的数据进行缓存,这样客户端只需从数据库查询一次数据,然后放入缓存中,以后再次查询的时候可以从缓存中读取,这样便提高了数据的访问速度,并发步骤如下:

  1. 准备工作

    开启Redis数据库,创建Spring Boot Web项目。使用MySql数据库创建user表用于项目开发数据的存储,如下:
    在这里插入图片描述

  2. 导入依赖

    在pom.xml文件中导入Redis数据库、持久层MyBatis、MySQL驱动等相关依赖(引入MySQL JDBC驱动时要根据自己安装的MySQL版本而定,win+r输入cmd,在终端输入mysql --version查看自己的MySQL版本,我的是8.0.24):

    <!-- mybatis 与 spring boot 2.x的整合包 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--mysql JDBC驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.24</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!--jedis连接池-->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
    
  3. 配置文件

    接下来在application.yml中配置Redis连接信息、MySQL数据库连接等相关信息:

    server:
      port: 8081
    
    #数据库连接
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?useUnicode=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: admin123
    
      ## Redis 配置
      redis:
        ## Redis数据库索引(默认为0)
        database: 0
        ## Redis服务器地址
        host: localhost
        ## Redis服务器连接端口
        port: 6379
        ## Redis服务器连接密码(默认为空)
        password:
        jedis:
          pool:
            ## 连接池最大连接数(使用负值表示没有限制)
            #spring.redis.pool.max-active=8
            max-active: 8
            ## 连接池最大阻塞等待时间(使用负值表示没有限制)
            #spring.redis.pool.max-wait=-1
            max-wait: -1
            ## 连接池中的最大空闲连接
            #spring.redis.pool.max-idle=8
            max-idle: 8
            ## 连接池中的最小空闲连接
            #spring.redis.pool.min-idle=0
            min-idle: 0
        ## 连接超时时间(毫秒)
        timeout: 1200
    
      #将themilef的默认缓存禁用,热加载生效
      thymeleaf:
        cache: false
    
      #mybatis的下划线转驼峰配置
      configuration:
        map-underscore-to-camel-case: true
    
        #另外一种打印语句的方式
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    #打印sql时的语句
    logging:
      level:
        com:
          acong:
            dao: debug
    
  4. 实体类

    创建与数据库相对应的User实体类:

    package com.shenziyi.db.entity;
    
    import java.io.Serializable;
    
    
    public class User implements Serializable {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    }
    
  5. 创建持久层

    接着是Mapper持久层Dao,这里主要用注解写比较方便,也可以使用MyBatis的XML配置文件写SQL语句:

    package com.shenziyi.db.Dao;
    
    import com.shenziyi.db.entity.User;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    
    
    @Mapper
    public interface UserDao {
    
        @Select("select * from user")
        List<User> queryAll();
    
        @Select("select * from user where id = #{id}")
        User findUserById(int id);
    
    
    }
    
  6. 业务层

    创建UserService,这里主要使用Redis模板来写:

    package com.shenziyi.db.service;
    
    
    import com.shenziyi.db.Dao.UserDao;
    import com.shenziyi.db.entity.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    
    @Service
    public class UserService {
    
        @Autowired
        private UserDao userDao;
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        public List<User> queryAll() {
            return userDao.queryAll();
        }
    
        /**
         * 获取用户策略:先从缓存中获取用户,没有则取数据表中 数据,再将数据写入缓存
         */
        public User findUserById(int id) {
            String key = "user_" + id;
    
            ValueOperations<String, User> operations = redisTemplate.opsForValue();
    
            //判断redis中是否有键为key的缓存
            boolean hasKey = redisTemplate.hasKey(key);
    
            if (hasKey) {
                User user = operations.get(key);
                System.out.println("从缓存中获得数据:" + user.getName());
                System.out.println("------------------------------------");
                return user;
            } else {
                User user = userDao.findUserById(id);
                System.out.println("查询数据库获得数据:" + user.getName());
                System.out.println("------------------------------------");
    
                // 写入缓存
                operations.set(key, user, 5, TimeUnit.HOURS);
                return user;
            }
        }
    }
    
  7. 控制层

    创建UserController,用于暴露访问接口:

    package com.shenziyi.db.controller;
    
    
    import com.shenziyi.db.entity.User;
    import com.shenziyi.db.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    
    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/queryAll")
        public List<User> queryAll(){
            List<User> lists = userService.queryAll();
            return lists;
        }
    
        @RequestMapping("/findUserById")
        public Map<String, Object> findUserById(@RequestParam int id){
            User user = userService.findUserById(id);
            Map<String, Object> result = new HashMap<>();
            result.put("id", user.getId());
            result.put("name", user.getName());
            result.put("pwd", user.getPwd());
            return result;
        }
    }
    
  8. 测试

    这里主要使用RedisTemplate来对Redis操作,每次访问controller暴露的接口,首先判断Redis缓存中是否存在该数据,若不存在就从数据库中读取数据,然后保存在Redis缓存中,当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行SQL语句,能够提高访问速度。但是当数据保存到缓存中时,需要设置键和值及超时删除,注意设置超市删除缓存时间不用太长,否则会给服务器压力。
    启动SpringBoot项目,在浏览器输入http://localhost:8081/findUserById?id=1,当我们第一次访问数据时从数据库获取,再次访问时则从缓存中获取保存的数据:(没有id为3的数据,所以报错)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

4.2 整合MySQL

4.2.1 SpringBoot整合MySQL

SpringBoot集成MySQL非常简单。SpringBoot连接数据库有四种方式:

  • 采用JDBC直接连接。
  • 采用JdbcTemplate连接。
  • 采用SpringDataJPA连接。
  • 框架连接。

采用JDBC方式直接连接烦琐,易错,我们直接略过,不做考虑。通过MyBatis、SpringDataJPA等连接,我们后续再讲。JdbcTemplate在JDBC的基础上做了大量的封装,本节采用JdbcTemplate连接MySQL。

  1. 引入依赖

    <!-- MySQL连接Java的驱动程序 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!-- 支持通过JDBC连接数据库 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    
  2. 添加数据库配置

    在application.yml文件中添加如下配置:

    spring:
      datasource:
        #MySQL连接信息   serverTimezone=GMT%2B8解决时区时间差报错问题
        url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
        # 账号
        username: root
        # 密码
        password: admin123
        # 驱动
        driver-class-name: com.mysql.jdbc.Driver
    
  3. 设计表和实体

    配置完信息之后,在test数据库中新建一张用户表user(之前已建好)

    表和数据准备好之后,在项目中新建User实体类:

    package com.shenziyi.entity;
    
    
    public class User {
        private int id;
        private String name;
        private String password;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
  4. 控制层

    创建UserController类:

    package com.shenziyi.controller;
    
    
    import com.shenziyi.entity.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowMapper;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.List;
    
    @Controller
    public class UserController {
        @Autowired
        JdbcTemplate jdbcTemplate;
    
        @ResponseBody
        @RequestMapping("/list")
        public List mySqlTest(){
            String sql="select * from user";
            /*query()是JdbcTemplate对象中的方法,RowMapper对象可以查询数据库中的数据*/
            List<User>users=jdbcTemplate.query(sql,new RowMapper<User>(){
                @Override
                /*RowMapper对象通过调用mapRow()方法将数据库中的每一行数据封装成User对象,并返回*/
                public User mapRow(ResultSet rs,int i)throws SQLException {
                    User user = new User();
                    user.setId(rs.getInt("id"));
                    user.setName(rs.getString("name"));
                    user.setPassword(rs.getString("password"));
                    return user;
                }
            });
            System.out.println("查询成功: "+users);
            return users;
        }
    }
    

    代码解释如下:

    • JdbcTemplate:JDBC连接数据库的工具类。
    • Query():query()是JdbcTemplate对象中的方法,RowMapper可以查询数据库中的数据。
    • mapRow():RowMapper对象通过调用mapRow()方法将数据库中的每一行数据封装成User对象并返回。

访问http://localhost:8080/list路径即可查询数据信息:
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值