SpringBoot学习笔记(七)
本文主要介绍SpringBoot整合JDBC、SpringBoot整合Druid和SpringBoot整合Mybatis
一、SpringBoot整合JDBC
对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。官网地址连接
- 创建测试项目测试数据源
1.新建一个项目测试:springboot-data-jdbc ,引入相关模块:
2.IDEA自动导入如下启动器:
<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>
3.编写yaml或者properties文件,连接数据库(这里有个大坑!!!)
spring:
datasource:
data-username: root
data-password: root
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
4.配置好这些就可以直接使用了(SpringBoot自动装配)
idea 连接数据库
去测试类测试:
package com.zhou;
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 SpringbootDataJdbcApplicationTests {
//DI注入依赖
@Autowired
DataSource dataSource;
@Test
void contextLoads() {
//查看默认的数据源
System.out.println(dataSource.getClass());
Connection connection=null;
try {
//获得连接,并打印
connection = dataSource.getConnection();
System.out.println(connection);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
//关闭连接
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
6.Run
报错:java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)
解决办法:修改application.yml配置文件
记住:username和password 前面不能加 data-
7.再次启动,查看到默认的数据源:class com.zaxxer.hikari.HikariDataSource
全局搜索,找到数据源相关的自动配置 :DataSourceAutoConfiguration
文件:
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link DataSource}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @author Kazuki Shimizu
* @since 1.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@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({ 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 {
}
//省略部分代码
- 另外,如 Spring Boot 1.5 默认使用
org.apache.tomcat.jdbc.pool.DataSource
作为数据源。在CSDN 看到一篇文章,介绍SpringBoot为什么选用Hikari作为默认的数据源,感兴趣的同学可以阅读:(我保存一下,嘻嘻~)追逐风的蝴蝶:关于springboot 的默认数据源
HikariCP的性能远高于c3p0、tomcat等连接池,以致后来BoneCP作者都放弃了维护,在Github项目主页推荐大家使用HikariCP。另外,Spring Boot将在2.0版本中把HikariCP作为其默认的JDBC连接池。
- JDBCTemplate
1.有了数据源(class com.zaxxer.hikari.HikariDataSource
),然后可以拿到数据库连接池(java.sql.Connection),有了连接就可以使用JDBC语句来操作数据库了。
2.Spring 本身也对原生的JDBC做了轻量级的封装,即JDBCTemplate,即使不使用第三方数据库操作框架,如Mybatis等。
3.数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。
4.SpringBoot不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需自己注入即可使用。
5.JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc
包下的 JdbcTemplateConfiguration
类
6.JdbcTemplateAutoConfiguration
源码:
- 在
JdbcTemplate
类中,可以看到大量的CURD操作:
JdbcTemplate主要提供以下几类方法:
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。
- 测试:
编写一个Controller,注入 jdbcTemplate
,编写测试方法进行访问测试:
package com.zhou.conroller;
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.List;
import java.util.Map;
@RestController
@RequestMapping("/jdbc")
public class JdbcController {
/**
* Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
* JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
* 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
*/
@Autowired
JdbcTemplate jdbcTemplate;
@GetMapping("/list")
public List<Map<String, Object>> userList(){
String sql = "select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
//新增
@GetMapping("/add")
public String addUser(){
String sql = "insert into user(id,name,password)value('8','zhouzhou','7880907')";
jdbcTemplate.update(sql);
return "addOk";
}
//修改
@GetMapping("/update/{id}")
public String updateUser(@PathVariable("id") int id){
String sql = "update user set name=?,password=? where id="+id;
Object[] person = new Object[2];
person[0] = "被修改的人";
person[1] = "2343234";
jdbcTemplate.update(sql,person);
return "updateOk";
}
//删除
@GetMapping("/delete/{id}")
public String delUser(@PathVariable("id") int id){
String sql = "delete from user where id=?";
jdbcTemplate.update(sql,id);
return "deleteOk";
}
}
- Run 测试 OK
list
add
update
delete
查询数据库,数据确实被进行 CURD 操作了
二、SpringBoot整合Druid
- Druid是一个JDBC组件,它包括三部分:
- DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。
- DruidDataSource 高效可管理的数据库连接池.
- SQLParser
- Druid可以做什么?
- 可以监控数据库访问性能;
- Druid提供了一个高效、功能强大、可扩展性好的数据库连接池;
- 数据库密码加密;
- Druid提供了不同的LogFilter(支持Common-Logging、Log4j和JdkLog)
- 扩展JDBC(通过Druid提供的Filter-Chain机制,编写JDBC层的扩展插件)
- Spring Boot 如何集成 Druid 数据源,如何实现数据库监控
DruidDataSource 参数配置详解
- 配置数据源
1、添加上 Druid 数据源依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.5</version>
</dependency>
2、切换数据源(SpringBoot 2.0以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源)
通过spring.datasource.type
指定数据源:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource #Druid
3、数据源切换之后,在测试类中注入 DataSource,然后测试是否成功切换:
4、切换成功后就可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等设置项:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource #Druid
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 4
minIdle: 4
maxActive: 20
maxWait: 30000
timeBetweenEvictionRunsMillis: 50000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
5.现在要为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了
(需要自己添加 DruidDataSource 组件到容器中,并绑定属性)
package com.zhou.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 {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
}
6.去测试类中测试:
package com.zhou;
import com.alibaba.druid.pool.DruidDataSource;
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 SpringbootDataJdbcApplicationTests {
//DI注入依赖
@Autowired
DataSource dataSource;
@Test
void contextLoads() {
//查看默认的数据源
System.out.println(dataSource.getClass());
Connection connection=null;
try {
//获得连接,并打印
connection = dataSource.getConnection();
System.out.println(connection);
DruidDataSource druidDataSource=(DruidDataSource) dataSource;
System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive());
System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
//关闭连接
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
报错:Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority
解决:导入Log4j 的依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
7.再次测试:OK
- 配置Druid数据源监控
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看。
1.需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理:
package com.zhou.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 {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
/**
* 配置 Druid 监控管理后台的Servlet
* SpringBoot内置 Servlet 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
* @return
*/
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean bean=new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername","root");
initParams.put("loginPassword","root");
//后台允许谁可以访问:
//initParams.put("allow", "localhost"):表示只有本机可以访问
//initParams.put("allow", ""):为空或者为null时,表示允许所有访问
initParams.put("allow","");
//deny:Druid 后台拒绝谁访问
//initParams.put("zhouzhou", "192.168.1.20");表示禁止此ip访问
//设置初始化参数
bean.setInitParameters(initParams);
return bean;
}
}
- 上面的参数不是瞎写的:可以在
com.alibaba.druid.support.http.StatViewServlet
的父类
com.alibaba.druid.support.http.ResourceServlet
中找到的:
com.alibaba.druid.support.http.ResourceServlet
类:
2.配置完毕,启动
3.访问:http://localhost:8081/druid/login.html
4.输入用户名和密码后:
工作中,按需求进行配置即可,主要用作监控。
三、SpringBoot整合Mybatis
整合MyBatis
官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
开始整合:
1.导入 Mybatis所需要的依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
2、配置数据库连接信息
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource #Druid
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 4
minIdle: 4
maxActive: 20
maxWait: 30000
timeBetweenEvictionRunsMillis: 50000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
thymeleaf:
cache: false
mybatis:
type-aliases-package: com.zhou.pojo
mapper-locations: classpath:mapper/*.xml
3、测试数据库是否连接成功
4.创建实体类:User.java
package com.zhou.pojo;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
5.创建mapper目录以及对应的 Mapper 接口
package com.zhou.mapper;
import com.zhou.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserMapper {
//获取所有User
List<User> getUser();
//通过id查找
User getUserById(Integer id);
}
6、Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhou.mapper.UserMapper">
<select id="getUser" resultType="User">
select * from user;
</select>
<select id="getUserById" resultType="User" parameterType="int">
select * from user
where id=#{id}
</select>
</mapper>
7、编写 UserController 进行测试
package com.zhou.conroller;
import com.zhou.mapper.UserMapper;
import com.zhou.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
@GetMapping("/getUser")
public List<User> getUser(){
return userMapper.getUser();
}
@GetMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id){
return userMapper.getUserById(id);
}
}
8..Run 测试 访问:http://localhost:8080/getUser
接续测试 访问:http://localhost:8080/getUserById/7
【注意】可能出现的报错:(上面的代码实例都是解决过的了,这里做为个人记录。)
前端显示:There was an unexpected error (type=Internal Server Error, status=500).
后端显示:org.thymeleaf.exceptions.TemplateInputException: Error resolving template [getUser], template might not exist or might not be accessible by any of the configured Template Resolvers
解决:
1.Maven 资源过滤问题
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<!--Maven 资源过滤问题-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
2.将 UserController类上的注解 @Controller
更改为 @RestController
(这里真的时太大意了,疏忽了)
3.在配置 mybatis 时,使用application.yml
或者application.properties
需要注意一下书写格式的不同,这里拿对比图记录一下。
还有,在application.yml
中配置 mybatis,我自作聪明的操作,不可取!