SpringBoot基础学习之整合JDBC框架

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个SpringBoot基础学习系列用来记录我学习SpringBoot框架基础知识的全过程 (这个系列是参照B站狂神的SpringBoot最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将会以一天一更的速度更新这个系列,还没有学习SpringBoot的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。
最后,希望能够和大家一同进步吧!加油吧!少年们!

废话不多说,让我们开始今天的学习内容吧,由于今天我们来到了SpringBoot基础学习的第六站:整合JDBC框架

6.1 整合JDBC框架

6.1.1 Spring Data简介

对于数据访问层,无论是SQL (关系型数据库) 还是NOSQL (非关系型数据库),Spring Boot底层都是采用Spring Data 的方式进行统一处理各种数据库,SpringData 也是Spring框架系列中与Spring Boot、Spring Cloud 等知名框架齐名的

Spring Data官网:https://spring.io/projects/spring-data

6.1.2 搭建基本环境

1.创建SpringBoot项目
1-1 选择Spring initializr项目

在这里插入图片描述

1-2 设置项目基本信息

在这里插入图片描述

1-3 引入相关资源依赖
  • 引入Spring Web、Thymeleaf和JDBC API、Spring Data JDBC及MySQL Driver相关资源依赖

在这里插入图片描述

2-4 设置项目存放位置

在这里插入图片描述

2-5 创建项目成功

在这里插入图片描述

2-6 删除多余文件

在这里插入图片描述

2.修改数据库驱动版本
2-1 修改pom.xml配置文件
  • 修改数据库驱动版本,默认引入的是8.0版本的驱动
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kuang</groupId>
    <artifactId>springboot-04-data</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-04-data</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- spring data的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <!-- JDBC的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- thymeleaf的资源依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- spring boot web的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MySQL数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!-- 将数据库驱动的scope默认的runtime修改为compile --> 
            <!-- <scope>runtime</scope> -->
            <scope>compile</scope>
            <!-- 将驱动版本修改为5.1.46版本 -->
            <version>5.1.46</version>
        </dependency>
        <!-- spring boot测试资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
2-2 查看资源依赖

在这里插入图片描述

3.连接MySQL数据库
3-1 编写核心配置文件

核心配置文件使用properties格式或者yaml格式都可以,看个人习惯,这里推荐使用yml格式

  • 使用properties格式编写核心配置文件
# 设置Tomcat服务器端口号
server.port=8888
# 设置数据库登录用户
spring.datasource.username=root
# 设置数据库登录密码
spring.datasource.password=123456
# 设置数据库url连接
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true
# 设置数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  • 使用yml格式编写核心配置文件
# 设置数据库驱动
spring:
  datasource:
    username: root
    password: 123456
    # MySQL 8.0版本以上的url链接格式
#    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    # MySQL 8.0版本以下的url链接格式
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true
    # 注意: com.mysql.cj.jdbc.Driver是8.0版本以上的数据库驱动, 而com.mysql.jdbc.Driver是8.0以下版本的数据库驱动
    # driver-class-name: com.mysql.cj.jdbc.Driver
    driver-class-name: com.mysql.jdbc.Driver
# 设置服务器端口号
server:
  port: 8888
3-2 连接MySQL数据库
  • 添加数据源,这里选择MySQL数据库

在这里插入图片描述

  • 设置数据库的登录用户名和密码,进行测试连接

在这里插入图片描述

  • 选择要连接的具体数据库

在这里插入图片描述

  • 数据库连接成功,右侧显示数据库表

在这里插入图片描述

3-3 数据库连接失败解决方案
  • 测试连接过程中遇到了

在这里插入图片描述

解决方法设置MySQL数据库的时区

1.连接mysql数据库
mysql  -u root -p

在这里插入图片描述

2.查看系统默认的时区
show variables like'%time_zone';

在这里插入图片描述

3.设置新的时区
set global time_zone = '+8:00'; 
4.查看修改后的时区
  • 这里注意要退出命令窗口后重新进入才可以看到修改成功后的时区
show variables like'%time_zone';

在这里插入图片描述

6.1.3 查看默认数据源和数据源自动配置原理

1.查看默认数据源
1-1 修改Springboot04DataApplicationTests测试类
package com.kuang;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class Springboot04DataApplicationTests {
    
    // 使用@Autowired注解将DataSource自动装配到Spring容器中
    @Autowired
    DataSource dataSource; // 数据源
    
    @Test
    void contextLoads() throws SQLException {
        // 查看默认的数据源:class com.zaxxer.hikari.HikariDataSource,相当于DBCP等数据源
        System.out.println(dataSource.getClass());
        // 获取数据库连接
        Connection connection  = dataSource.getConnection();
        // 打印connection连接信息
        System.out.println(connection);
        // xxx Template:SpringBoot已经配置好模板bean,拿来即用 CRUD
        // 关闭数据库连接
        connection.close();
    }
    
}
1-2 首次测试结果

在这里插入图片描述

结果测试失败,出现测试引擎的ID’ junit_jupiter’不能找到的错误

1-3 解决测试引擎ID无法找到问题
  • 在pom.xml配置文件的测试资源依赖中添加vintage引擎
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kuang</groupId>
    <artifactId>springboot-04-data</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-04-data</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- spring data的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <!-- JDBC的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- thymeleaf的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- spring boot web的资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MySQL数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!-- 将数据库驱动的scope默认的runtime修改为compile --> 
            <!-- <scope>runtime</scope> -->
            <scope>compile</scope>
            <!-- 将驱动版本修改为5.1.46版本 -->
            <version>5.1.46</version>
        </dependency>
        <!-- spring boot测试资源依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <!-- 由于测试类报错,所以需要要添加vintage引擎 -->
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • 在右侧的Maven管理中使用clean清除,重新导入资源依赖

在这里插入图片描述

1-4 重新测试结果

在这里插入图片描述

结果SpringBoot默认的数据源是class com.zaxxer.hikari.HikariDataSource

2.数据源自动配置的原理
2-1 jdbc数据源位置
  • 首先在项目左侧的外部资源中找到spring-boot.autoconfigure-2.45的资源jar包

在这里插入图片描述

  • 然后在org.springframework.boot.autoconfigure包路径下找到jdbc包,最后在metadata包下的JdbcTemplateAutoConfiguration配置类

在这里插入图片描述

2-2 DataSourceProperties属性类源码浅析
  • 查看DataSourceProperties数据源属性类源码
/**
 * 数据源配置的基本类
 *
 * @author Dave Syer
 * @author Maciej Walkowiak
 * @author Stephane Nicoll
 * @author Benedikt Ritter
 * @author Eddú Meléndez
 * @author Scott Frederick
 * @since Spring 1.1.0
 */

// 使用@ConfigurationProperties注解, 设置可有效绑定到此对象的属性前缀, 这里设置为"spring.datasource"(prefix前缀的value值一般使用"."进行分隔)
@ConfigurationProperties(prefix = "spring.datasource")
// DataSourceProperties(数据源属性)类, 实现BeanClassLoaderAware(Bean类加载器软件)和InitializingBean(初始化Bean)接口
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
    
	private ClassLoader classLoader; // 类加载器
    
	private String name; // 数据库名称
    
	private boolean generateUniqueName = true; // 是否生成随机的数据源名称
    
     // 要使用连接池实现类的全限定名,默认情况下它从类路径自动检测
	private Class<? extends DataSource> type;
    
     // JDBC驱动的全限定名,默认情况下根据URL自动检测
	private String driverClassName;
    
	private String url; // 数据库JDBC的链接
    
	private String username; // 数据库的登录用户名
    
	private String password; // 数据库的登录密码
    
    // 设置jndiName(jndi表示Java本地目录接口)后,数据源JNDI类的位置,url链接,用户名和密码都会被忽略
	private String jndiName;

    //确定是否应使用可用的DDL(全称为Data definition language, 表示数据定义语言)和DML(全称为Data Manipulation Language, 即数据操作语言)脚本执行数据源初始化时,应用该模式
	private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED;

	/**
	* 使用DDL或者DML脚本的平台(例如schema-${platform(平台)}.sql或者data(数据)-${platform(平台)}.sql)
	 */
	private String platform = "all";

	/**
	 * 数据库(DDL, 数据定义语言)脚本的资源依赖.
	 */
	private List<String> schema;

	/**
	 * 去执行DDL(数据定义语言)脚本的数据库用户名(如果不相同). 
	 */
	private String schemaUsername;

	/**
	 * 去执行DDL(数据定义语言)脚本的数据库密码(如果不相同). 
	 */
	private String schemaPassword;

	/**
	 * 数据(DML, 数据查询语句)脚本资源依赖
	 * Data (DML) script resource references.
	 */
	private List<String> data;

	/**
	 * 去执行DML脚本的数据库用户名(如果不相同).
	 */
	private String dataUsername;

	/**
	 * 去执行DML脚本的数据库密码(如果不相同).
	 */
	private String dataPassword;

	/**
	 * 在初始化数据库时, 如果发生错误是否去停止
	 */
	private boolean continueOnError = false;

	/**
	 * SQL初始化脚本中的语句分隔器
	 */
	private String separator = ";";

	/**
	 * SQL脚本字符集
	 */
	private Charset sqlScriptEncoding;

    // 内置的数据库连接
	private EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection.NONE;

    // 获取Xa的实例化对象(Xa表示具体的数据源设置信息)
	private Xa xa = new Xa();

    //唯一名
	private String uniqueName; 
    
    
    //...(省略中间部分代码)...
    
    // 获取Xa值的get方法
    public Xa getXa() {
		return this.xa;
	}
   
    // 设置Xa值的set方法
	public void setXa(Xa xa) {
		this.xa = xa;
	}

	/**
	 * XA表示具体的数据源设置信息
	 * XA Specific datasource settings.
	 */
	public static class Xa {

		/**
		 * XA数据源的全限定名
		 */
		private String dataSourceClassName;

		/**
		 * 要传递给XA数据源的属性.
		 */
		private Map<String, String> properties = new LinkedHashMap<>();

        // 属性对应的get和set方法
		public String getDataSourceClassName() {
			return this.dataSourceClassName;
		}

		public void setDataSourceClassName(String dataSourceClassName) {
			this.dataSourceClassName = dataSourceClassName;
		}

		public Map<String, String> getProperties() {
			return this.properties;
		}

		public void setProperties(Map<String, String> properties) {
			this.properties = properties;
		}

	}
    
   //...(省略后面部分代码)...
            
}
  • 查看@ConfigurationProperties注解源码
package org.springframework.boot.context.properties;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

/**
 * 外部化配置的注释. 
 * 如果你想要去绑定和验证一些外部的属性(即一个.properties配置文件), 则添加到类定义或者在使用@Configuration注解的类中, 使用@Bean注解的方法上
 * 绑定可以通过调用带有注解的类中的setter方法来执行或者, 或者如果使用ConstructorBinding(构造器绑定, 即使用@@ConstructorBinding注解), 则通过绑定到构造函数参数来执行
 * 注意: 与Value值相反, SpEL表达式不会被计算, 因为属性值是外部化的
 *
 * @author Dave Syer
 * @since 1.0.0版本
 */
// 使用@Target注解, 设置作用目标, 元素类型选择类型和方法, 多个属性使用{}包裹, 使用","进行分隔
@Target({ ElementType.TYPE, ElementType.METHOD })
// 使用@Retention注解, 设置保留时间, 保留策略选择运行期间
@Retention(RetentionPolicy.RUNTIME)
// 使用@Documented注解, 该注解将由javadoc和类型工具记录, 并且成为注解元素的公共API的一部分
@Documented
public @interface ConfigurationProperties {

	/**
	 * 可有效的绑定到此对象的属性前缀, 相当于"#prefix()"的同义词.
	 * 有效的前缀由一个或者多个用点分隔的单词定义 (例如"acme.system.feature"("顶点.系统.特征").
	 * @return 绑定属性的前缀
	 */
	@AliasFor("prefix")
	String value() default "";

	/**
	 * 可有效的绑定到此对象的属性前缀, 相当于"#value()"的同义词.
	 * 有效的前缀由一个或者多个用电分隔的单词定义(例如"acme.system.feature"("顶点.系统.特征").
	 * @return 绑定属性的前缀
	 */
	@AliasFor("value")
	String prefix() default "";

	/**
	 * 该标志表示等到绑定该对象时, 有效的字段应该被忽略.
	 * Flag to indicate that when binding to this object invalid fields should be ignored.
	 * 根据所使用的binder(绑定器), 无效意味着无效, 通常这表示字段类型错误(或无法强制转换为正确类型)
	 * @return 标志的值(默认值为false)
	 */
	boolean ignoreInvalidFields() default false;

	/**
	 * 该标志表示等到绑定该对象时, 未知的字段应该被忽略.
	 * 未知的字段可能表示属性中存在错误
	 * An unknown field could be a sign of a mistake in the Properties.
	 * @return 标志值 (默认为true)
	 */
	boolean ignoreUnknownFields() default true;

}
  • 查看@AliasFor注解源码
package org.springframework.core.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @AliasFor是一个用于声明注释属性别名的注解
 * @author Sam Brannen
 * @since Spring 4.2 版本
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {

	/**
	 * “attribute”表示属性的别名
	 * 当”#annotation“注解没有声明"&mdash"(这是HTML中的代码写法, 表示"破折号-")时, 用来代替"#attribute"属性
	 * 例如: 使用@AliasFor("value")来代替@AliasFor(attribute = "value")
	 */
	@AliasFor("attribute")
	String value() default "";

	/**
	 * 此属性作为属性名称的别名
	 */
	@AliasFor("value")
	String attribute() default "";

	/**
	 * 声明带有"#attribute"别名的注解类型
	 * 默认值为"Annotation"(注解)类, 这意味着别名属性是与该属性在相同的注解中声明
	 */
	Class<? extends Annotation> annotation() default Annotation.class;

}
  • 查看DataSourceAutoConfiguration配置类的源码
// 使用@Configuration注解, 将当前类注册为配置类, 交由Spring的IOC容器统一管理, 将proxyBeanMethods(动态Bean方法)的属性值设置为false, 表示不使用动态代理
@Configuration(proxyBeanMethods = false)
// 使用@ConditionalOnClass注解, 表示Spring的IOC容器中包含指定类: DataSource(数据源)类和EmbeddedDatabaseType(内置的数据库类型)类
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
// 使用@ConditionalOnMissingBean注解, 表示Spring的IOC容器中不存在指定Bean, 属性类型为io.r2dbc.spi.ConnectionFactory(连接工厂)
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
// 使用@EnableConfigurationProperties注解, 表示开启配置属性
@EnableConfigurationProperties(DataSourceProperties.class)
// 使用@Import注解, 表示在该类中导入其他类: DataSourcePoolMetadataProvidersConfiguration(数据源池元数据提供者配置)类和DataSourceInitializationConfiguration(数据源初始化配置)类
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
// 数据源自动配置类
public class DataSourceAutoConfiguration {
    
    @Configuration(proxyBeanMethods = false)
	@Conditional(EmbeddedDatabaseCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import(EmbeddedDataSourceConfiguration.class)
    // 内置的数据库配置类
	protected static class EmbeddedDatabaseConfiguration {

	}
    
    @Configuration(proxyBeanMethods = false)
	@Conditional(PooledDataSourceCondition.class)
    /**
     * 使用@ConditionalOnMissingBean注解, 表示Spring的IOC容器中不存在指定Bean:
     * DataSource(数据源)类和XADataSource(具体的数据源)类
     * 注意: 如果数据源DataSource类不存在,下面的数据源自动配置就失效了)
     */
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    /** 
     * 使用@Import注解, 表示在当前类中导入其他类: 这里为数据源配置类
     * 主要包括Hikari(也就是SpringBoot默认的数据源), 还有Tomca和DBCP等数据源,
     */
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
			DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
    // 池数据源的配类置
	protected static class PooledDataSourceConfiguration {

	}
    
    // 池数据源条件:检查是否存在其他数据源类型
	static class PooledDataSourceCondition extends AnyNestedCondition {
		PooledDataSourceCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}
        // 条件成立才添加到容器中
		@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
		static class ExplicitType {
		}
		@Conditional(PooledDataSourceAvailableCondition.class)
		static class PooledDataSourceAvailable {
		}
	}
    
    //...(省略后面部分代码)...
    
}
  • 查看DataSourceConfiguration配置类源码
// 抽象类数据源配置类
abstract class DataSourceConfiguration {

    // 使用@SuppressWarnings注解, 镇压未检查的警告
	@SuppressWarnings("unchecked")
	protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
		return (T) properties.initializeDataSourceBuilder().type(type).build();
	}

    // Tomcat数据源配置
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
			matchIfMissing = true)
	static class Tomcat {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.tomcat")
		org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
			org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(properties,
					org.apache.tomcat.jdbc.pool.DataSource.class);
			DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
			String validationQuery = databaseDriver.getValidationQuery();
			if (validationQuery != null) {
				dataSource.setTestOnBorrow(true);
				dataSource.setValidationQuery(validationQuery);
			}
			return dataSource;
		}

	}

	// Hikari数据源配置
	@Configuration(proxyBeanMethods = false)
    // 判断Hikari数据源类是否存在
	@ConditionalOnClass(HikariDataSource.class)
    // 判断是否缺失数据源类
	@ConditionalOnMissingBean(DataSource.class)
    // 判断是否在配置文件中设置属性数据源类型
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
	static class Hikari {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		HikariDataSource dataSource(DataSourceProperties properties) {
			HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
			if (StringUtils.hasText(properties.getName())) {
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}

    // DBCP数据源的配置
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource",
			matchIfMissing = true)
	static class Dbcp2 {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.dbcp2")
		org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties) {
			return createDataSource(properties, org.apache.commons.dbcp2.BasicDataSource.class);
		}
        
         //...(省略后面部分代码)...
        
    }
}

结论我们可以发现当前的 Spring Boot 2.4.5版本默认使用的是com.zaxxer.hikari.HikariDataSource,即Hikari数据源;而之前老版本,如Spring Boot 1.5版本, 默认org.apache.tomcat.jdbc.pool.DataSource,即Tomact数据源

HikariDataSource号称Java Web 当前速度最快的数据源,相比与传统的C3P0DBCPTomcatJDBC等连接池更加优秀

2-3 查看dbcTemplateAutoConfiguration模板自动配置类源码
  • 查看JdbcTemplateAutoConfiguration自动配置类源码
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(JdbcProperties.class)
// 导入JDBC模板配置类
@Import({ JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class })
// JDBC模板自动配置类
public class JdbcTemplateAutoConfiguration {

}
  • 查看JdbcTemplateConfiguration配置类源码
@Configuration(proxyBeanMethods = false)
// 如果JdbcOperations(JDBC操作类)不存在,那么下面的JDBC模板就不生效
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {
    
    // 将jdbcTemplate注册到IOC容器中
	@Bean
	@Primary
    // 注入DataSource(数据源)和JdbcProperties(JDBC配置类),SpringBoot已经帮我们搞定了
	JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		JdbcProperties.Template template = properties.getTemplate();
		jdbcTemplate.setFetchSize(template.getFetchSize());
		jdbcTemplate.setMaxRows(template.getMaxRows());
		if (template.getQueryTimeout() != null) {
			jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
		}
		return jdbcTemplate;
	}

}

6.1.4 使用JDBC进行增删改查

1.使用JDBC实现查询用户
1-1 编写控制器JdbcController
package com.kuang.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

// 使用@RestController注解,实现Controller接口并且返回值为字符串
@RestController
public class JdbcController {
    
    // 使用@Autowired注解,自动装配JdbcTemplate(JDBC模板)类到Spring容器中
    @Autowired
    JdbcTemplate jdbcTemplate;

    // 查询用户列表信息
    // 没有实体类,数据库中的内容,怎么获取?可以使用万能的Map
    // 真实访问路径:http://localhost:8080/getList
    // 使用@RequestMapping注解,设置请求映射路径
    @RequestMapping("/getList")
    public List<Map<String, Object>> getUserList() {
        // 封装SQL查询语句到字符串sql中去
        String sql = "select * from user";
        // 调用JDBC模板引擎的queryForList来获取用户数组集合信息
        List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
        // 返回到用户集合
       return list_maps;
    }
    
}
1-2 测试结果

在这里插入图片描述

2.使用JDBC实现增加用户
2-1 编写控制器JdbcController
package com.kuang.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

// 使用@RestController注解,实现Controller接口并且返回值为字符串
@RestController
public class JdbcController {
    
    // 使用@Autowired注解,自动装配JdbcTemplate(JDBC模板)类到Spring容器中
    @Autowired
    JdbcTemplate jdbcTemplate;
    
    // 增加用户信息
    // 真实访问路径:http://localhost:8080/addUser
    // 使用@RequestMapping注解,设置请求映射路径
    @RequestMapping("/addUser")
    public String addUser() {
        // 封装SQL增加语句到字符串sql中去
        String sql = "insert into mybatis.user(id,name,pwd) values(7,'陈奕迅','cyx123456')";
        // JDBC模板调用update方法进行插入数据
        jdbcTemplate.update(sql);
        // 返回一个"Add-OK"
        return "Add-OK";
    }
    
}
2-2 测试结果
  • 页面输入请求

在这里插入图片描述

  • 查看数据库表

在这里插入图片描述

3.使用JDBC实现修改用户
3-1 编写控制器JdbcController
package com.kuang.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

// 使用@RestController注解,实现Controller接口并且返回值为字符串
@RestController
public class JdbcController {
    
    // 使用@Autowired注解,自动装配JdbcTemplate(JDBC模板)类到Spring容器中
    @Autowired
    JdbcTemplate jdbcTemplate;

    // 修改用户信息
    // 真实访问路径:http://localhost:8080/updateUser
    // 使用@RequestMapping注解,设置请求映射路径
    @RequestMapping("/updateUser/{userId}")
    public String updateUser(@PathVariable("userId") int id) {
        // 封装SQL修改语句到字符串sql中去
        String sql = "update mybatis.user set name=?,pwd=? where id="+id;
        // 封装数据
        Object[] objects = new Object[2];
        objects[0] = "张学友";
        objects[1] = "zxy123456";
        // JDBC模板调用update方法进行修改数据
        jdbcTemplate.update(sql,objects);
        // 返回一个"Update-OK"
        return "Update-OK";
    }
    
}
3-2 测试结果
  • 页面输入请求

在这里插入图片描述

  • 查看数据库表

在这里插入图片描述

4.使用JDBC实现删除用户
4-1 编写控制器JdbcController
package com.kuang.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

// 使用@RestController注解,实现Controller接口并且返回值为字符串
@RestController
public class JdbcController {
    
    // 使用@Autowired注解,自动装配JdbcTemplate(JDBC模板)类到Spring容器中
    @Autowired
    JdbcTemplate jdbcTemplate;

    // 修改用户信息
    // 真实访问路径:http://localhost:8080/deleteUser
    // 使用@RequestMapping注解,设置请求映射路径
    @RequestMapping("/deleteUser/{userId}")
    public String delteUser(@PathVariable("userId") int id) {
        // 封装SQL修改语句到字符串sql中去
        String sql = "delete from mybatis.user where id=?";
        // JDBC模板调用update方法进行修改数据
        jdbcTemplate.update(sql,id);
        // 返回一个"Update-OK"
        return "Delete-OK";
    }
    
}
4-2 测试结果
  • 页面输入请求

在这里插入图片描述

  • 查看数据库表

在这里插入图片描述

好了,今天的有关 SpringBoot基础学习之整合JDBC框架 的学习就到此结束啦,欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连,我们下期见,拜拜啦!


参考视频链接:https://www.bilibili.com/video/BV1PE411i7CV(【狂神说Java】SpringBoot最新教程IDEA版通俗易懂)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔の蜗牛rz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值