SpringBoot_数据访问-JDBC&自动配置原理

整合最基本的JDBC和数据源,第一个MYSQL,导入mysql驱动的,第二个我们使用原生的JDBC,后面使用Mybatis和JPA

再选相应的内容就行了,为了演示方便我也把WEB模块选中,我们在pom文件里引入的是什么呢,引入是starter-jdbc

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

<dependency>
	<!-- 引入web模块 -->
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>

我们使用最基本的JDBC的时候呢,引入这两个模块,一个是JDBC,一个是MYSQL驱动,我们让他自动导入,接下来我们要看

如何配置,才能跟数据库交互呢,我们连上虚拟机的数据库,我已经在这启动起来了,启动起来以后我们用客户端连上,

我们把mysql启动起来,我们数据库启动起来了,我们要怎么连上数据库呢,有了Springboot我们只需要写相应的配置

就行了,那我们来到src/main/resources下,就在这写配置,写什么配置呢,spring.datasource数据源,datasource里面

有一些属性,比如我们写数据库要用的username,

spring.datasource.username=root

spring.datasource.password=123456

比如我们要连的url地址,我们专门来创建一个测试库,day20,我们就连上他来操作,配置URL,

spring.datasource.url=jdbc:mysql://localhost:3306/day20

我们驱动的类名

spring.datasource.driver-class-name=com.mysq.jdbc.Driver

这样一配就算是好了

我们可以来测试一下,我们来到test类里面
#debug=true
#server.port=8081

#server.context-path=/boot02

spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true

logging.level.com.learn=trace
#logging.file=D:/springboot.log
logging.file=springboot.log
#logging.path=/spring/log
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd} ==== [%thread] %-5level ==== %logger{50} ==== %msg%n
#spring.resources.static-locations=classpath:/hello,classpath:/learn

spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/day20
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
DataSource我们让他自动注入,从容器中拿到的数据源是什么,再从数据源里拿一条链接,

看能不能拿到这个链接,看到数据源用的是这种,class org.apache.tomcat.jdbc.pool.DataSource,

他用的是tomcat数据源,连接ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@60b34931]],

这种配置的默认规则就是这样,我们想要访问数据库,只需要做一个简单的配置,就是这一块配置,配置的效果,

默认的是tomcat.jdbc数据源,他作为数据源
package com.learn.springboot;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * SpringBoot单元测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootDataJDBCApplicationTests {
	
	@Autowired
	DataSource dataSource;
	
	@Test
	public void contextLoads() throws SQLException {
		// org.apache.tomcat.jdbc.pool.DataSource
		System.out.println(dataSource.getClass());
		Connection connection = dataSource.getConnection();
		System.out.println(connection);
		connection.close();
	}
}
包括我们这一块的配置,它是Spring.jdbc,我们点进来,其实跟我们这个类有关的,数据源所有的配置都在

DataSourceProperties里面,为什么是这样的效果,包括我们可以自动装配到数据源,而且springboot使用tomcat.jdbc的

连接池作为数据源的,我们可以看一下数据源自动配置原理,这个原理我们可以打开自动配置包

org.springframework.boot.autoconfigure.jdbc

这里都是和数据源配置的,配置原理就是在这个包下,我来抓住几个比较重要的来给大家看一下,第一个这里有一个

DataSourceAutoConfiguration,这里是数据源的自动配置,DataSourceConfiguration,这里叫数据源的配置,这里的

@Bean来给容器中添加组件,都是加DataSource,这个类就是来数据源的,但是加哪些数据源,根据各种判断,如果你导入

了tomcat.jdbc连接池,并且你配的spring.datasource.type是jdbc,如果你没配他也会认为你是配了的

/**
 * Tomcat Pool DataSource configuration.
 */
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", 
havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
static class Tomcat extends DataSourceConfiguration {

这个时候就导入tomcat.jdbc的数据源,否则如果是其他情况,

/**
 * Hikari DataSource configuration.
 */
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", 
havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
static class Hikari extends DataSourceConfiguration {

如果是Hikari,而且你在type里面指定了HikariDataSource,那么他也能创建这种数据源,参考DataSourceConfiguration,

根据配置创建数据源,默认使用tomcat连接池的,那他作为数据源的,我们可以使用什么指定呢,可以使用

spring.datasource.type他来指定自定义的数据源类型,比如我们使用c3p0,包括dbcp等等,而Springboot能支持哪些

数据源呢,自带支持的就有这么多,tomcat的jdbc,还支持Hikari的jdbc,还有dbcp的BasicDataSource,包括dbcp2的数据源,

我们也可以指定自己的,如果我们指定的数据源类型不是以上的,他就用这种来给我们创建数据源

/**
 * Generic DataSource configuration.
 */
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {

	@Bean
	public DataSource dataSource(DataSourceProperties properties) {
		return properties.initializeDataSourceBuilder().build();
	}

}

自定义数据源,自定义数据源类型,这里他有一个机制,如果你是自定义数据源的类型,数据源是怎么创建出来呢,

/**
 * Initialize a {@link DataSourceBuilder} with the state of this instance.
 * @return a {@link DataSourceBuilder} initialized with the customizations defined on
 * this instance
 */
public DataSourceBuilder initializeDataSourceBuilder() {
	return DataSourceBuilder.create(getClassLoader()).type(getType())
			.driverClassName(determineDriverClassName()).url(determineUrl())
			.username(determineUsername()).password(determinePassword());
}

使用DataSourceBuilder来创建数据源的,Builder创建数据源的步骤呢,

public DataSource build() {
	Class<? extends DataSource> type = getType();
	DataSource result = BeanUtils.instantiate(type);
	maybeGetDriverClassName();
	bind(result);
	return result;
}

调用build方法来创建数据源,他就是用BeanUtils工具进行反射,并且绑定相关的属性,利用反射创建相应type

的数据源,并且绑定相关属性,这里有一个DataSourceAutoConfiguration,数据源的自动配置,

@Bean
@ConditionalOnMissingBean
public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,
		ApplicationContext applicationContext) {
	return new DataSourceInitializer(properties, applicationContext);
}

DataSourceInitializer的作用是什么,DataSourceInitializer是ApplicationListener,它是一个监听器,

而这个ApplicationListener,我们在Spring注解版的时候,给大家有讲过,大家可以去参考他的原理,我们就来

说一下他的作用,这个作用就是两处,我们直接参考这个类就行了,这个类上的解释也看到,初始化的时候可以

帮我们运行schema,

/**
 * Bean to handle {@link DataSource} initialization by running {@literal schema-*.sql} on
 * {@link PostConstruct} and {@literal data-*.sql} SQL scripts on a
 * {@link DataSourceInitializedEvent}.
 *
 * @author Dave Syer
 * @author Phillip Webb
 * @author Eddú Meléndez
 * @author Stephane Nicoll
 * @author Kazuki Shimizu
 * @since 1.1.0
 * @see DataSourceAutoConfiguration
 */
class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> {

包括data的sql文件,第一个叫@PostConstruct

@PostConstruct
public void init() {
	if (!this.properties.isInitialize()) {
		logger.debug("Initialization disabled (not running DDL scripts)");
		return;
	}
	if (this.applicationContext.getBeanNamesForType(DataSource.class, false,
			false).length > 0) {
		this.dataSource = this.applicationContext.getBean(DataSource.class);
	}
	if (this.dataSource == null) {
		logger.debug("No DataSource found so not initializing");
		return;
	}
	runSchemaScripts();
}

数据源刚创建好,创建好对象以后,要调用这个方法,这个方法他从容器中拿到数据源,拿到数据源以后runSchemaScripts,

这是他的第一个作用,运行建表语句,我们把建表语句放到指定位置,人家就能够执行了,还有一步叫onApplicationEvent,

这就是我们的监听器,在我们监听到一个事件以后,调用这个方法

@Override
public void onApplicationEvent(DataSourceInitializedEvent event) {
	if (!this.properties.isInitialize()) {
		logger.debug("Initialization disabled (not running data scripts)");
		return;
	}
	// NOTE the event can happen more than once and
	// the event datasource is not used here
	if (!this.initialized) {
		runDataScripts();
		this.initialized = true;
	}
}

这个方法还能runDataScripts,运行插入数据的语句,这样我们把建表和插入数据的相关的SQL文件,放进来就行了,

而它默认的规则是什么,默认只需要将文件命名为,如果是建表的就命名为schema-.sql,如果是数据的,那你就命名为

data-*.sql这种形式的sql,就这么来命名就行了,就是这两种文件,就是在Initializer里面运行的,正好我们有一个

建表语句,来看我们能不能把相应的表创建出来,我们在跑建表语句的时候,那要先得到scripts,得到这个而文件,

private List<Resource> getScripts(String propertyName, List<String> resources,
		String fallback) {
	if (resources != null) {
		return getResources(propertyName, resources, true);
	}
	String platform = this.properties.getPlatform();
	List<String> fallbackResources = new ArrayList<String>();
	fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
	fallbackResources.add("classpath*:" + fallback + ".sql");
	return getResources(propertyName, fallbackResources, false);
}

/**
 * Platform to use in the DDL or DML scripts (e.g. schema-${platform}.sql or
 * data-${platform}.sql).
 */
private String platform = "all";

spring.datasource.schema= # Schema (DDL) script resource references.

spring.datasource.schema=classpath:department.sql

JdbcTemplateAutoConfiguration,如果有数据源的情况下,他还会给我们容器中添加一个JdbcTemplate

@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
	return new JdbcTemplate(this.dataSource);
}

@Bean
@Primary
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
	return new NamedParameterJdbcTemplate(this.dataSource);
}

这都是学Spring底层操作数据库,自动配置了JdbcTemplate操作数据库,我们要操作数据库呢,我来写一个最简单的演示

方法
注入JdbcTemplate,jdbcTemplate可以直接注入的

http://localhost:8080/query
package com.learn.controller;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
	
	@Autowired
	JdbcTemplate jdbcTemplate;
	
	@ResponseBody
	@GetMapping("/query")
	public Map<String,Object> map(){
		List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from department");
		return list.get(0);
	}
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值