整合最基本的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);
}
}