简介
- 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。
- Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库,Spring Data 也是 Spring 中与 Spring Boot、Spring Cloud 等齐名的知名项目。
- Sping Data 官网:https://spring.io/projects/spring-data
数据库相关的启动器 :可以参考官方文档:https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
整合JDBC
pom导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
yml编写链接数据库配置
# spring jdbc 链接属性配置
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:8889/zentao?userUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
# 5.x 版本使用jdbc.driver,之后版本使用cj.driver
配置完成之后可以直接去使用,因为springboot已经默认完成了一些自动配置,可以搞个类来测试一下 ```java package com.addicated;
import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException;
@SpringBootTest class Springboot03WebApplicationTests {
@Resource
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
// 默认数据源打印出来为 class com.zaxxer.hikari.HikariDataSource
System.out.println(dataSource.getClass());
// 获取数据源链接 抛出异常处理
Connection connection = dataSource.getConnection();
// xxx Template springboot已经配置好的模板bean,拿来即用
// jdbcTemplate
// redisTemplate crud方法都防撞在template中
System.out.println(connection);
connection.close();
}
}
- 默认数据源打印为hikari
- 接下来来看源码,全局搜索一下,找到数据源所有的自动配置在 DataSourceAutoConfiguration 这个类中
<a name="P5QoN"></a>
# JDBCTemplate
- 有了数据源,然后可以拿到数据库链接,有了链接,就可以使用原声的JDBC语句来操作数据库。
- 即使不使用第三方数据库操作框架,如MyBatis等,Spring 本身也对原生的JDBC做了轻量级的封装,即JdbcTemplate。
- 数据库操作的所有 CRUD 方法都在 JdbcTemplate中
- Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需要自己注入即可使用
- JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的JdbcTemplateConfiguration 类
- JdbcTemplate主要提供以下几类方法:
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句
- update方法以及batchUpdate方法:update方法用于执行新增,修改,删除等语句,batchUpdate方法用于执行批处理相关语句。
- query方法及queryForXXX方法:用于执行查询相关语句
- call方法:用于执行存储过程,函数相关语句
<a name="QcF2G"></a>
# 测试
- 编写一个controller,注入jdbcTemplate,编写测试方法进行访问测试。
```java
package com.kuang.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/jdbc")
public class JdbcController {
/**
* Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
* JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
* 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
*/
@Autowired
JdbcTemplate jdbcTemplate;
//查询employee表中所有数据
//List 中的1个 Map 对应数据库的 1行数据
//Map 中的 key 对应数据库的字段名,value 对应数据库的字段值
@GetMapping("/list")
public List<Map<String, Object>> userList(){
String sql = "select * from employee";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
//新增一个用户
@GetMapping("/add")
public String addUser(){
//插入语句,注意时间问题
String sql = "insert into employee(last_name, email,gender,department,birth)" +
" values ('狂神说','24736743@qq.com',1,101,'"+ new Date().toLocaleString() +"')";
jdbcTemplate.update(sql);
//查询
return "addOk";
}
//修改用户信息
@GetMapping("/update/{id}")
public String updateUser(@PathVariable("id") int id){
//插入语句
String sql = "update employee set last_name=?,email=? where id="+id;
//数据
Object[] objects = new Object[2];
objects[0] = "xxx";
objects[1] = "24736743@sina.com";
jdbcTemplate.update(sql,objects);
//查询
return "updateOk";
}
//删除用户
@GetMapping("/delete/{id}")
public String delUser(@PathVariable("id") int id){
//插入语句
String sql = "delete from employee where id=?";
jdbcTemplate.update(sql,id);
//查询
return "deleteOk";
}
}
Druid
简介
- JAVA程序很大一部分要操作DB,为了提高性能操作数据库的时候,又不得不使用数据库链接池。
- Druid 是阿里开源平台上一个数据库链接池实现,结合了 C3P0,DBCP 等 DB 池的优点,同时加入了日志监控。
- Druid 可以很好的监控 DB 池链接和 SQL 的执行情况,天生就是针对监控而生的DB链接池。
- Druid 已经在阿里部署了超过600个应用,经过很多考验。
- SpringBoot 2.0 以上默认使用Hikari 数据源,可以说 Hikari 与 Druid 都是当前 Java Web上最优秀的数据源,下面介绍一下springboot 如何集成 Druid 数据源,如何实现数据库监控。
- Git: https://github.com/alibaba/druid/
- com.alibaba.druid.pool.DruidDataSource 的基本配置见下图
配置数据源
- 添加上Druid 数据源依赖 ```java
- 切换数据源:springboot 2.0 以上默认使用 hikari数据源,但是可以通过spring.datasource.type 指定数据源
```java
# spring jdbc 链接属性配置
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:8889/zentao?userUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
# 5.x 版本使用jdbc.driver,之后版本使用cj.driver
# type: com.zaxxer.hikari.HikariDataSource
type: com.alibaba.druid.pool.DruidDataSource
- 切换之后在测试类中尝试获取到数据源,检查是否生效
切换成功,既然切换成功,就可以设置数据源链接初始化大小,最大连接数,等待时间,最小连接数 等设置, 可以查看源码进行学习
# spring jdbc 链接属性配置
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:8889/zentao?userUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
# 5.x 版本使用jdbc.driver,之后版本使用cj.driver
# type: com.zaxxer.hikari.HikariDataSource
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
导入log4j依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
现在需要自己为 DuirdDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用SpringBoot的自动生成了,需要自己添加 DruidDataSource 组建到容器中,并绑定属性 ```java package com.kuang.config;
import com.alibaba.druid.pool.DruidDataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration public class DruidConfig {
/*
将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
@ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
- 进行测试,是否有druid的属性配置注入
- ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1617810610179-281cea13-e4d4-43f6-8a87-683b547846bb.png#align=left&display=inline&height=341&margin=%5Bobject%20Object%5D&name=image.png&originHeight=682&originWidth=1333&size=502733&status=done&style=none&width=666.5)
<a name="lki4M"></a>
## 配置数据源监控
- Druid 数据源具有监控的功能,并且提供了一个web页面方便用户进行查看,类似安装路由器时,提供的一个默认的web管理页面
- 第一步需要设置Druid的后台管理页面,比如登陆账号,密码等,配置后台管理
```java
package com.addicated.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
/*
将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
@ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet
// 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin"); //后台管理界面的登录账号
initParams.put("loginPassword", "123456"); //后台管理界面的登录密码
//后台允许谁可以访问
//initParams.put("allow", "localhost"):表示只有本机可以访问
//initParams.put("allow", ""):为空或者为null时,表示允许所有访问
initParams.put("allow", "");
//deny:Druid 后台拒绝谁访问
//initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问
//设置初始化参数
bean.setInitParameters(initParams);
return bean;
}
//2.配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
- 在工作中用到的时候按需进行配置,主要用来监控