> 文章列表 > 【零基础入门SpringBoot2】—— 数据访问专题

【零基础入门SpringBoot2】—— 数据访问专题

【零基础入门SpringBoot2】—— 数据访问专题

一、SQL

  • 导入数据库开发的相关场景 + 配置数据库依赖
  • SpringBoot对数据访问层的整合,都是 spring-boot-data 开头

1、数据源的自动配置

(1)导入JDBC场景

<!--数据库相关依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

【零基础入门SpringBoot2】—— 数据访问专题

  • 我们需要确保数据库版本和驱动版本一致,为什么官方导入JDBC场景不包含驱动呢
    • 因为数据库有很多种,官方不知道我们要使用的是哪种数据库
  • 数据库驱动的默认版本:<mysql.version>8.0.22</mysql.version>
    • 我们如何将驱动指定为我们需要的版本呢?
      • 方法一:在pom.xml中直接引入具体版本的依赖【maven的就近依赖原则】
      • 方法二:通过在pom.xml的properties标签中指定驱动版本 【maven属性的就近优先原则】
        <properties><java.version>1.8</java.version><mysql.version>5.1.49</mysql.version>
        </properties>
        

(2)分析自动配置

  • DataSourceAutoConfiguration: 数据源的自动配置
    • 修改数据源相关的配置:spring.datasource
    • 数据库连接池的配置,是自己容器中没有DataSource才自动配置的
    • 底层配置好的连接池是:HikarDataSource
	@Configuration(proxyBeanMethods = false)@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })protected static class PooledDataSourceConfiguration
  • DataSourceTransactionManagerAutoConfiguration:事务管理器的自动配置

  • JdbcTemplateAutoConfiguration:JdbcTemplate的自动配置,可以来对数据库进行增删改查

    • 可以修改这个配置项 @ConfigurationProperties(prefix = “spring.jdbc”) 来修改 JdbcTemplate
    • @Bean@Primary JdbcTemplate, 容器中有这个组件 【我们通过@Autowire注解直接注入使用即可】
  • JndiDataSourceAutoConfiguration: jndi 的自动配置

  • XADataSourceAutoConfiguration: 分布式事务相关的

(3)修改配置项 【就是我们需要对我们操作的数据库进行配置】

  • 我们的application.yml 一般是完成与数据相关的配置
spring:datasource:url: jdbc:mysql://localhost:3306/smbmsusername: rootpassword: 111111driver-class-name: com.mysql.jdbc.Driver

(4)我们测试是否可以成功操作数据库

  • 测试方法直接写在主程序测试类中,这个是我们通过模版快速创建的

【零基础入门SpringBoot2】—— 数据访问专题

package com.atguigu.admin;import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;@SpringBootTest
@Slf4j
class Boot05WebAdminApplicationTests {@AutowiredJdbcTemplate jdbcTemplate;@Testvoid contextLoads() {//查询表中的数据
//        jdbcTemplate.queryForObject("select * from smbms_user");
//        jdbcTemplate.queryForList("select * from smbms_user");Long aLong = jdbcTemplate.queryForObject("select count(*) from smbms_user", Long.class);log.info("记录总数: {}", aLong);}}

【零基础入门SpringBoot2】—— 数据访问专题

2、使用Druid数据源

  • 整合阿里提供的第三方数据源
    • 方法一:自定义
    • 方法二:找官方提供的场景(starter)

(1)自定义方式

创建数据源

  • 引入德鲁伊连接池的依赖:

    <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.17</version>
    </dependency>
    
  • 下面这张图我想说明:如果我们在容器中没有自定义数据源,那么系统会给我们创建HikariDataSource数据源

【零基础入门SpringBoot2】—— 数据访问专题

  • 之前我们在Spring自定义数据源时,需要通过bean标签配置,或者采用set方法设置
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="maxActive" value="20" /><property name="initialSize" value="1" /><property name="maxWait" value="60000" /><property name="minIdle" value="1" /><property name="timeBetweenEvictionRunsMillis" value="60000" /><property name="minEvictableIdleTimeMillis" value="300000" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /><property name="poolPreparedStatements" value="true" /><property name="maxOpenPreparedStatements" value="20" />
  • 在SpringBoot中,我们只需要通过 @ConfigurationProperties 指向我们的配置文件,就可以实现属性自动绑定

    @Configuration
    public class MyDataSourceConfig {@Bean@ConfigurationProperties("spring.datasource")public DataSource dataSource(){DruidDataSource druidDataSource = new DruidDataSource();return druidDataSource;}
    }
    

StatViewServlet

  • StatViewServlet 的用途包括:

    • 提供监控信息展示的html页面

    • 提供监控信息的JSON API

      	<servlet><servlet-name>DruidStatView</servlet-name><servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class></servlet><servlet-mapping><servlet-name>DruidStatView</servlet-name><url-pattern>/druid/*</url-pattern></servlet-mapping>
      
  • 配置Druid的监控页功能

    /* 配置druid的监控页功能* @return*/
    @Bean
    public ServletRegistrationBean statViewServlet() {StatViewServlet statViewServlet = new StatViewServlet();ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");// 监控页账号密码registrationBean.addInitParameter("loginUsername", "admin");registrationBean.addInitParameter("loginPassword"," 123456");return registrationBean;
    }
    

StatFilter

  • 用于统计监控信息:如果SQL监控、URI监控

    需要给数据源中配置如下属性;可以允许多个filter,多个用,分割;如:<property name="filters" value="stat,slf4j" />
    

【零基础入门SpringBoot2】—— 数据访问专题

慢SQL记录配置:

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"><property name="slowSqlMillis" value="10000" /><property name="logSlowSql" value="true" />
</bean>使用 slowSqlMillis 定义慢SQL的时长

(2)使用官方 starter 方式

引入 德鲁伊数据源的starter

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version>
</dependency>

我们查看场景中的配置,分析一下SpringBoot为我们完成了哪些自动配置

  • 先定位到自动配置类

【零基础入门SpringBoot2】—— 数据访问专题

@Configuration
@ConditionalOnClass({DruidDataSource.class})
@AutoConfigureBefore({DataSourceAutoConfiguration.class})
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
  • ConditionalOnClass 说明容器中有DruidDataSource的组件才会生效
  • 这个配置文件在默认的数据源自动配置类之前生效,为的是让我们自定义的数据源代替默认的数据源
  • EnableConfigurationProperties 的作用是与我们的配置文件关联上,实现属性的绑定
    • DruidStatProperties.class 对应@ConfigurationProperties(“spring.datasource.druid”)
    • DataSourceProperties.class 对应@ConfigurationProperties(prefix = “spring.datasource”)
  • 又利用 @Import 注解导入四个配置 【把类加入Spring IOC容器】
    • DruidSpringAopConfiguration.class

      • 通过spring.datasource.druid.aop-patterns进行配置
      • 作用是监控Spring的组件的
    • DruidStatViewServletConfiguration.class

      • 通过spring.datasource.druid.stat-view-servlet进行配置
      • 作用是完成监控页的配置
    • DruidWebStatFilterConfiguration.class

      • 通过spring.datasource.druid.web-stat-filter进行配置
      • 作用是web监控配置
    • DruidFilterConfiguration.class

      • Druid 自己的filter配置
          private static final String FILTER_STAT_PREFIX = "spring.datasource.druid.filter.stat";private static final String FILTER_CONFIG_PREFIX = "spring.datasource.druid.filter.config";private static final String FILTER_ENCODING_PREFIX = "spring.datasource.druid.filter.encoding";private static final String FILTER_SLF4J_PREFIX = "spring.datasource.druid.filter.slf4j";private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j";private static final String FILTER_LOG4J2_PREFIX = "spring.datasource.druid.filter.log4j2";private static final String FILTER_COMMONS_LOG_PREFIX = "spring.datasource.druid.filter.commons-log";private static final String FILTER_WALL_PREFIX = "spring.datasource.druid.filter.wall";private static final String FILTER_WALL_CONFIG_PREFIX = "spring.datasource.druid.filter.wall.config";
      

接下来我们要演示具体是如何进行配置以及使用的

  • 下面这个文件是我在项目的 application.yml 中进行配置的

    spring:datasource:url: jdbc:mysql://localhost:3306/smbmsusername: rootpassword: 111111driver-class-name: com.mysql.jdbc.Driverdruid:filters: stat,wall # 指定开启哪些功能[此处分别为 sql监控、防火墙]stat-view-servlet: # 监控页功能enabled: truelogin-password: admin # 监控登录密码login-username: admin # 监控登录账号reset-enable: falseweb-stat-filter: # web监控和uri监控enabled: trueexclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*' # 不指定默认就是这个url-pattern: /*aop-patterns: com.atguigu.admin.* # 监控这个包下的所有组件filter: # 对于上面拦截器/过滤器的详细配置stat:slow-sql-millis: 1000 # 指定超过1s的查询都是慢查询log-slow-sql: true # 是否开启慢查询日志记录功能enabled: truewall:enabled: trueconfig:delete-allow: false # 禁止删表操作jdbc:template:query-timeout: 3
    
  • 如果我们想来到druid的监控页

    • 在浏览器的地址栏输入: localhost:8080/druid/login.html
    • 然后输入我们配置好的德鲁伊连接池的账号和密码

【零基础入门SpringBoot2】—— 数据访问专题

  • 给出Druid官方配置手册:
    • 点击跳转Druid Spring Boot Starter中文手册

3、整合MyBatis操作

  • JdbcTemplateSpring内置的简单版数据库操作工具,在平时工作的时候我们会使用第三方提供的数据库操作工具,例如:MyBatis
  • 使用MyBatis之前,先引入对应的starter的依赖
        <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency>

(1)配置模式

  • SpringBoot 底层为我们做了什么?

    • SqlSessionFactory 自动配置好了
    • SqlSession 中自动配置了 SqlSessionTemplate 并组合了SqlSession
    • 通过 @Import(AutoConfiguredMapperScannerRegistrar.class) 导入对应组件
    • 我们编写的Mapper接口,通过@Mapper扫描进来
  • 通过 @EnableConfigurationProperties注解实现与配置文件的绑定

    @EnableConfigurationProperties(MybatisProperties.class)MyBatis配置项绑定类。
    @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
    public class MybatisAutoConfiguration{}@ConfigurationProperties(prefix = "mybatis")
    public class MybatisProperties
    
  • 先看下一目录结构,了解都创建了哪些文件

    • Account 代表封装数据库字段的POJO
    • 我们把请求的处理写在了 IndexController 控制器中
    • mapper.AccountMapper 接口设置了操作数据库的方法,此处为 getAcct
    • service.AccountService 类调用了接口对象,创建了一个业务方法调用接口方法实现功能
    • resources目录下的mybatis目录专门存放于mybatis相关的
      • mybatis-config.xml 是mybatis的核心配置文件,后期可以省略直接在springboot的yaml文件中进行配置
      • AccountMapper.xml 来完成具体的映射

【零基础入门SpringBoot2】—— 数据访问专题

  • 接下来描述一下整体通过配置MyBatis操作数据库的流程:
    • 导入mybatis官方starter
    • 编写mapper接口并使用@Mapper注解
    • 编写sql映射文件并绑定到mapper接口上
    • 在application.yaml 中指定Mapper核心配置文件位置、sql映射文件位置
  • yaml中的配置 【对于采取配置文件和configuration配置只能选取一种】
# 配置mybatis的规则
mybatis:
#  config-location: classpath:mybatis/mybatis-config.xml # 指定mybatis全局文件的位置mapper-locations: classpath:mybatis/mapper/*.xml # 指定mybatis的sql映射文件位置configuration:map-underscore-to-camel-case: true # 通过配置文件的方式开启驼峰映射

接下来附上我们的各个文件

//AccountMapper 接口
package com.atguigu.admin.mapper;import com.atguigu.admin.bean.Account;
import org.apache.ibatis.annotations.Mapper;/* @author Bonbons* @version 1.0*/
@Mapper
public interface AccountMapper {public Account getAcct(Long id);
}
//AccountService类
package com.atguigu.admin.service;import com.atguigu.admin.bean.Account;
import com.atguigu.admin.mapper.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/* @author Bonbons* @version 1.0*/
@Service
public class AccountService {//注入操作数据库的对象@AutowiredAccountMapper accountMapper;public Account getAcctById(Long id){return accountMapper.getAcct(id);}
}
<!--AccountMapper.xml 映射文件-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.admin.mapper.AccountMapper"><!--根据id查询用户信息--><select id="getAcct" resultType="com.atguigu.admin.bean.Account">select * from account_tbl where id = #{id}</select>
</mapper>
<!--此处的目的是开启驼峰映射,以后大多就不设置mybatis的核心配置文件了-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>

【零基础入门SpringBoot2】—— 数据访问专题

  • 一些补充知识点:
    • 当我们的@Bean注解用于方法上,参数类型如果在容器中有对应组件,那么就会从容器中取

【零基础入门SpringBoot2】—— 数据访问专题
【零基础入门SpringBoot2】—— 数据访问专题

(2)注解模式

  • 不需要编写mybatis的核心配置文件与sql映射文件
  • 整体流程
    • 第一步,仍然需要导入 mybatis 的 starter
    • 第二步,编写我们的POJO类,此处为 City
    • 第三步,编写我们的mapper接口,此处和我们以往不同,直接通过注解来指明对应的SQL语句
    • 第三步,编写我们的 CityServer(业务层),在业务里调用mapper层的方法
    • 第四步,在我们的控制器(此处为 IndexController)中编写方法,处理我们的请求
  • 接下来附上我们的文件代码
// City类
package com.atguigu.admin.bean;import lombok.Data;/* @author Bonbons* @version 1.0*/
@Data
public class City {private Long id;private String name;private String state;private String country;
}
// CityMapper接口
package com.atguigu.admin.mapper;import com.atguigu.admin.bean.City;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;/* @author Bonbons* @version 1.0*/
@Mapper
public interface CityMapper {//不去编写sql映射文件了,而是直接在我们接口方法的上方通过注解来指定@Select("select * from city where id = #{id}")public City getById(Long id);
}
// CityService类
package com.atguigu.admin.service;import com.atguigu.admin.bean.City;
import com.atguigu.admin.mapper.CityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/* @author Bonbons* @version 1.0*/
@Service
public class CityService {//注入我们的mapper@AutowiredCityMapper cityMapper;public City getById(Long id){return cityMapper.getById(id);}
}
//控制器方法
//纯注解的方式
@Autowired
CityService cityService;
@GetMapping("/city")
@ResponseBody
public City getCityById(@RequestParam("id") Long id){return cityService.getById(id);
}

【零基础入门SpringBoot2】—— 数据访问专题

(3)混合模式

  • 什么情况下会混合 配置文件 + 注解的形式呢?

    • 就是当我们的SQL很复杂的时候
    • 就是不使用注解代替sql映射文件【对于我们采取配置文件的部分】
  • 可以参考下面的这几部分代码:

// CityMapper接口
package com.atguigu.admin.mapper;import com.atguigu.admin.bean.City;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;/* @author Bonbons* @version 1.0*/
@Mapper
public interface CityMapper {//不去编写sql映射文件了,而是直接在我们接口方法的上方通过注解来指定@Select("select * from city where id = #{id}")public City getById(Long id);//这个不采用注解的方式,与配置文件结合使用完成插入功能public void insert(City city);
}
// CityService类
package com.atguigu.admin.service;import com.atguigu.admin.bean.City;
import com.atguigu.admin.mapper.CityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/* @author Bonbons* @version 1.0*/
@Service
public class CityService {//注入我们的mapper@AutowiredCityMapper cityMapper;public City getById(Long id){return cityMapper.getById(id);}public void saveCity(City city){cityMapper.insert(city);}
}
<!--CityMapper.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.admin.mapper.AccountMapper"><!--插入City数据--><insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into city(`name`, `state`, `country`) values(#{name}, #{state}, #{country})</insert>
</mapper>
//IndexController控制器
//纯注解的方式 >> 查询@AutowiredCityService cityService;@GetMapping("/city")@ResponseBodypublic City getCityById(@RequestParam("id") Long id){return cityService.getById(id);}//注解+配置文件 >> 添加@ResponseBody@PostMapping("/city")public City saveCity(City city){cityService.saveCity(city);return city;}
//普通Java对象类
package com.atguigu.admin.bean;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/* @author Bonbons* @version 1.0*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {private Long id;private String name;private String state;private String country;
}

我们也可以将第二种配置方式转为注解方式【内含配置项的注解用法】

@Insert("insert into city(`name`, `state`, `country`) values(#{name}, #{state}, #{country})")
@Options(useGeneratedKeys = true, keyProperty = "id")
public void insert(City city);
  • 补充知识点:
    • useGeneratedKeys、keyProperty 代表设置自增键
    • 用@Options注解指定选项
    • 主程序类使用@MapperScan(“com.atguigu.admin.mapper”) 注解扫描所有mapper,代替每个接口上使用@mapper注解
  • 总结注解和配置方式使用Mybatis的最佳实战:
    • 引入 mybatis-starter 的场景
    • 在SpringBoot的核心配置文件 application.yaml 中,指定 mapper-location 的位置 【sql映射文件】
    • 编写Mapper接口并标注@Mapper注解 【尽管上面可以通过包扫描代替标记@Mapper,但还是推荐使用@Mapper注解】
    • 对于接口中的写法有两种方式
      • 简单写法就是直接通过注解代替sql映射文件
      • 复杂写法就是编写sql文件,然后与我们的mapper接口方法关联上 【大多用于比较复杂的SQL】

4、整合MyBatis-Plus 完成CRUD

(1)什么是 MyBatis-Plus

  • 是MyBatis的增强工具,可以简化开发、提升效率
  • IDEA中有相关的插件:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装
  • 具体的开发指南可以参考我们的 MyBatisPlus 官网

(2)整合MyBatis-Plus

整体流程说明:

  • 准备数据库表【我使用的是mysql的navicat】

    • 创建表的脚本
    CREATE TABLE user
    (id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
    );
    
    • 创建几组对应数据的脚本
    INSERT INTO user (id, name, age, email) VALUES
    (1, 'Jone', 18, 'test1@baomidou.com'),
    (2, 'Jack', 20, 'test2@baomidou.com'),
    (3, 'Tom', 28, 'test3@baomidou.com'),
    (4, 'Sandy', 21, 'test4@baomidou.com'),
    (5, 'Billie', 24, 'test5@baomidou.com');
    
  • 引入mybatisPlus的starter

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>
  • 编写Mapper接口
package com.atguigu.admin.mapper;import com.atguigu.admin.bean.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/* @author Bonbons* @version 1.0* 让我们的接口直接继承MyBatisPlus提供的BaseMapper* 泛型为我们要操作的数据类型*/
public interface UserMapper extends BaseMapper<User> {
}
  • 编写我们数据库表对应的POJO类
    • 此处为什么不直接删掉userName、password属性呢?
      • 因为在登录验证的时候要使用
package com.atguigu.admin.bean;import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/* @author Bonbons* @version 1.0*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {/* 正常所有的属性都应该与数据库表中的字段对应上* 但是上面的userName和 password 我们暂时用不到,所以就通过注解暂时让他俩不在表中*/@TableField(exist = false)private String userName;@TableField(exist = false)private String password;//MyBatisPlus整合用的User对象为下面四个字段private Long id;private String name;private Integer age;private String email;
}
  • 编写测试方法【这个方法是写在我们的 主程序测试类中的】

【零基础入门SpringBoot2】—— 数据访问专题

@Autowired
UserMapper userMapper;
@Test
void testUserMapper(){User user = userMapper.selectById(1L);log.info("用户信息: {}", user);
}

【零基础入门SpringBoot2】—— 数据访问专题

  • 其实还应该配置数据源,我们在之前已经配置了 Druid 数据源此处使用的就是【直接贴上我的 application.yml】
spring:datasource:url: jdbc:mysql://localhost:3306/smbmsusername: rootpassword: 111111driver-class-name: com.mysql.jdbc.Driverdruid:filters: stat,wall # 指定开启哪些功能[此处分别为 sql监控、防火墙]stat-view-servlet: # 监控页功能enabled: truelogin-password: admin # 监控登录密码login-username: admin # 监控登录账号reset-enable: falseweb-stat-filter: # web监控和uri监控enabled: trueexclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'url-pattern: /*aop-patterns: com.atguigu.admin.* # 监控这个包下的所有组件filter: # 对于上面拦截器/过滤器的详细配置stat:slow-sql-millis: 1000 # 指定超过1s的查询都是慢查询log-slow-sql: true # 是否开启慢查询日志记录功能enabled: truewall:enabled: trueconfig:delete-allow: false # 禁止删表操作jdbc:template:query-timeout: 3# 配置mybatis的规则
mybatis:
#  config-location: classpath:mybatis/mybatis-config.xml # 指定mybatis全局文件的位置mapper-locations: classpath:mybatis/mapper/*.xml # 指定mybatis的sql映射文件位置configuration:map-underscore-to-camel-case: true # 通过配置文件的方式开启驼峰映射

接下来我们对 mybatis-plus 场景的自动配置进行分析

  • 在starter中,自动配置是从 spring.factories 里面获取EnableAutoConfiguration 以启动要加载的类
    • 项目一启动 MybatisPlusAutoConfiguration 的自动配置就会生效
      • MybatisPlusProperties 配置项绑定【mybatis-plus:xxx 就是对mybatis-plus的定制】
      • SqlSessionFactory 自动配置好,在底层使用的是容器中默认的数据源
      • mapperLocations 自动配置好的。有默认值为 classpath*:/mapper//*.xml;【任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件】
      • 容器中也自动配置好了 SqlSessionTemplate
      • @Mapper 标注的接口也会被自动扫描;建议直接 @MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行

补充的其他知识点:

  • @Bean标记一个方法,如果参数是一个对象,这个参数就会从容器中自动确定这个组件

  • Ctrl + F12 查看类中有哪些方法 【IDEA快捷键】

  • 只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力 【当然我们如果有特殊的需求,也可以使用sql映射文件自定义】

    • 以下是BaseMapper中为我们提供的一些基本方法

    【零基础入门SpringBoot2】—— 数据访问专题

(3)CRUD功能

  • 零散知识点:

    • 对于我们定义的Mapper接口,继承BaseMapper之后,它如何知道我们关联的是数据库中的那张表呢?
      • 默认将泛型参数首字母小写为数据库中对应的表,比如此处为 BaseMapper<User> 默认对应数据库中的 user 表
      • 当然,我们也可以指定POJO类对应的表名,在我们的POJO类上添加注解@TableName(“实际表名”)即可【此处为User】
    • 遍历状态: stat.count 可以充当编号 直接用id也行
  • UserService

    /* 继承顶级 Service*/
    public interface UserService extends IService<User> {}
    
  • UserServiceImpl

    package com.atguigu.admin.service.impl;import com.atguigu.admin.bean.User;
    import com.atguigu.admin.mapper.UserMapper;
    import com.atguigu.admin.service.UserService;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.springframework.stereotype.Service;/* @author Bonbons* @version 1.0*/
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    }
    
  • Controller

    @GetMapping("/dynamic_table")
    public String dynamic_table(Model model) {// 从数据库中查出user表中的用户进行展示List<User> list = userService.list();model.addAttribute("users", list);return "table/dynamic_table";
    }
    
  • 修改前端页面

    <tr><th>#</th><th>id</th><th>name</th><th>ages</th><th>email</th><th>操作</th>
    </tr>
    </thead>
    <tbody>
    <tr class="gradeX" th:each="user,stat:${users}"><td th:text="${stat.count}">Trident</td><td th:text="${user.id}">id</td><td th:text="${user.name}">InternetExplorer 4.0</td><td th:text="${user.age}"></td><td class="center hidden-phone">[[${user.email}]]</td><td class="center hidden-phone">X</td>
    </tr>
    
  • 效果演示

【零基础入门SpringBoot2】—— 数据访问专题

演示分页功能的使用:

  • 编写一个分页插件的配置类
@Configuration
public class MyBatisConfig {/* MybatisPlusInterceptor* @return*/@Beanpublic MybatisPlusInterceptor paginationInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// MyBatis-plus3.4版本以后的分页拦截器PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false// paginationInterceptor.setOverflow(false);paginationInnerInterceptor.setOverflow(true);// 设置最大单页限制数量,默认 500 条,-1 不受限制// paginationInterceptor.setLimit(500);paginationInnerInterceptor.setMaxLimit(500L);mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);return mybatisPlusInterceptor;}
}
  • Controller中增加分页功能

    @GetMapping("/dynamic_table")
    public String dynamic_table(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {// 从数据库中查出user表中的用户进行展示List<User> list = userService.list();//model.addAttribute("users", list);// 分页查询数据Page<User> userPage = new Page<>(pn, 2);// 分页查询的结果Page<User> page = userService.page(userPage, null);model.addAttribute("page", page);return "table/dynamic_table";
    }
    
  • 修改前端页面,演示分页效果

    <div class="row-fluid"><div class="span6"><div class="dataTables_info" id="dynamic-table_info">当前第 [[${page.current}]] 页总计 [[${page.pages}]] 页共 [[${page.total}]] 条记录</div></div><div class="span6"><div class="dataTables_paginate paging_bootstrap pagination"><ul><li class="prev disabled"><a href="#">← 前一页</a></li><li th:class="${num == page.current?'active':''}"th:each="num:${#numbers.sequence(1,page.pages)}"><a th:href="@{/dynamic_table(pn=${num})}">[[${num}]]</a></li><li class="next disabled"><a href="#">下一页 → </a></li></ul></div></div>
    </div>
    

【零基础入门SpringBoot2】—— 数据访问专题
【零基础入门SpringBoot2】—— 数据访问专题

实现删除功能

  • 增加删除的按钮:

    <td><ath:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}"class="btn btn-danger btn-sm"type="button">删除</a>
    </td>
    
  • 设置控制器方法:

    @GetMapping("/user/delete/{id}")
    public String deleteUser(@PathVariable("id") Long id,@RequestParam(value = "pn", defaultValue = "1") Integer pn,RedirectAttributes ra) {userService.removeById(id);ra.addAttribute("pn", pn);return "redirect:/dynamic_table";
    }
    

【零基础入门SpringBoot2】—— 数据访问专题


二、NoSQL

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

1、Redis自动配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

【零基础入门SpringBoot2】—— 数据访问专题

  • 分析一下Redis-start在底层为我们完成了哪些配置
    • 自动配置类为 RedisAutoConfiguration,指明了RedisProperties属性类(属性绑定)
      • 通过 spring.redis.xxx 完成对 redis 的配置 【在application.xml 中食用】
    • LettuceConnectionConfiguration、JedisConnectionConfiguration连接工厂也是准备好的
    • 为我们自动注入了两个操作Redis的模版:
      • RedisTemplate<Object, Object>StringRedisTemplate 【区别就是kv的类型不同,后者专门用于String】
      • 底层只要我们通过@Autowire注入了 StringRedisTemplate或RedisTemplate就可以操作Redis
  • 为了掩饰操作Redis,推荐去阿里云申请一个按时计费的Redis
    • 阿里云按量付费redis。经典网络
    • 申请redis的公网连接地址
    • 修改白名单 允许0.0.0.0/0 访问

2、RedisTemplate 与 Lettuce

  • 在我们SpringBoot的核心配置文件: application.properties 中对redis进行配置:
spring:redis:host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.comport: 6379password: lfy:Lfy123456
  • 然后编写测试方法,看是否能连接上我们的阿里云Redis
@Autowired
StringRedisTemplate redisTemplate;@Test
void testRedis() {ValueOperations<String, String> operations = redisTemplate.opsForValue();operations.set("hello", "world");String hello = operations.get("hello");System.out.println(hello);
}
  • 上面采用的是系统默认的 lettuce 客户端,用于连接 RedisServer 的
    • 我们还可以通过jedis客户端连接我们的Redis
    • 那么我们该如何切换客户端呢?

3、切换到jedis

  • 导入Jedis的依赖
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>
  • 通过核心配置文件,将redis的客户端类型设置为 jedis
spring:redis:host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.comport: 6379password: lfy:Lfy123456client-type: jedis
  • 通过测试方法,输出一下当前的客户端类型
@Autowired
RedisConnectionFactory redisConnectionFactory;@Test
void testRedis(){// org.springframework.data.redis.connection.jedis.JedisConnectionFactorySystem.out.println(redisConnectionFactory.getClass());
}

4、利用Redis实现URL访问次数统计功能

  • 创建一个URL统计拦截器 【在控制器方法执行前执行】
@Component
public class RedisUrlCountInterceptor implements HandlerInterceptor {@AutowiredStringRedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String uri = request.getRequestURI();// 默认每次访问当前uri就会计数+1redisTemplate.opsForValue().increment(uri);return true;}
}
  • 在配置类中将我们定义的拦截器注册到IOC容器中
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {@AutowiredRedisUrlCountInterceptor redisUrlCountInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(redisUrlCountInterceptor).addPathPatterns("/").excludePathPatterns("/","/login","/css/","/fonts/","/images/","/js/","/aa/");}
}

【零基础入门SpringBoot2】—— 数据访问专题

  • 在我们的控制器方法中,利用 StringRedisTemplate 统计数据
@Slf4j
@Controller
public class IndexController {@AutowiredStringRedisTemplate redisTemplate;@GetMapping("/main.html")public String mainPage(HttpSession session, Model model) {log.info("当前方法是:{}", "mainPage");ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();String s = opsForValue.get("/main.html"); // 获取main.html页面访问的次数String s1 = opsForValue.get("/sql");      // 获取sql请求访问的次数model.addAttribute("mainCount", s);model.addAttribute("sqlCount", s1);return "main";}
}
  • 修改对应页面的前端表单
<div class="col-md-6 col-xs-12 col-sm-6"><div class="panel purple"><div class="symbol"><i class="fa fa-gavel"></i></div><div class="state-value"><div class="value" th:text="${mainCount}">230</div><div class="title">/main.html</div></div></div>
</div>
<div class="col-md-6 col-xs-12 col-sm-6"><div class="panel red"><div class="symbol"><i class="fa fa-tags"></i></div><div class="state-value"><div class="value" th:text="${sqlCount}">3490</div><div class="title">/sql</div></div></div>
</div>

【零基础入门SpringBoot2】—— 数据访问专题

  • 补充知识点:Filter 和 Interceptor 几乎有相同的功能,那么有什么区别呢?
    • Filter 是Servlet的原生组件,脱离Spring应用也能使用
    • Interceptor 是Spring定义的接口,可以使用Spring的自动装配功能 [@Autowired]