SpringBoot【三】 整合 JDBC、Druid、MyBatis
Spring Data
对于数据访问层,无论是 SQL(关系型数据库)还是 NOSQL(非关系型数据库),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.3.1.RELEASE/reference/htmlsingle/#using-boot-starter
整合 JDBC
-
创建测试项目,引入【Web】 Spring Web、【SQL】JDBC API、MySQL Driver 依赖
-
项目建好之后,已经自动帮我们导入了如下的启动器:
<!--web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--JDBC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
-
编写 yaml 配置文件连接数据库
spring: datasource: username: root password: root # 假如时区报错了,就增加一个时区的配置 serverTimezone=UTC url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver
-
配置完这些就可以直接使用了,因为 SpringBoot 已经默认帮我们进行了自动配置,测试类测试
@SpringBootTest class Springboot04DataApplicationTests { @Autowired //DI注入数据源 DataSource dataSource; @Test void contextLoads() throws SQLException{ // 查看默认的数据源 class com.zaxxer.hikari.HikariDataSource System.out.println(dataSource.getClass()); // 获得数据库连接 Connection connection = dataSource.getConnection(); System.out.println(connection); // 关闭连接 connection.close(); } }
-
结果:默认配置的数据源为 :
class com.zaxxer.hikari.HikariDataSource
数据源配置分析:
数据源的所有自动配置都在 :DataSourceAutoConfiguration
中
@Import({ DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.Generic.class,
DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
这里导入的类都在 DataSourceConfiguration
中,默认使用 HikariDataSource 数据源,而以前版本,如 SpringBoot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源。
可以使用 spring.datasource.type 指定自定义的数据源类型,值为要使用的连接池实现的完全限定名。
HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀。
JdbcTemplate
- 有了数据源(com.zaxxer.hikari.HikariDataSource),就拿到数据库连接(java.sql.Connection),有了连接,就可以使用原生的 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 方法:用于执行存储过程、函数相关语句。
CRUD 操作:编写一个 Controller 类,注入 jdbcTemplate,编写测试方法进行访问测试
@RestController
public class JDBCController {
/**
* Spring Boot 默认提供了数据源,默认提供了 org.springframework.jdbc.core.JdbcTemplate
* JdbcTemplate 中会自己注入数据源,用于简化 JDBC操作
* 还能避免一些常见的错误,使用起来也不用再自己来关闭数据库连接
*/
@Autowired
JdbcTemplate jdbcTemplate;
//查询数据库所有信息
// 没有实体类,数据库中的东西怎么获取?map
// List 中的1个 Map 对应数据库的 1行数据
// Map 中的 key 对应数据库的字段名,value 对应数据库的字段值
@GetMapping("/userList")
public List<Map<String, Object>> userList(){
String sql = "select * from user";
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return maps;
}
@GetMapping("/addUser")
public String addList(){
String sql = "insert into mybatis.user(id, name, pwd) VALUES (4,'赵六','123456')";
jdbcTemplate.update(sql);
return "add-ok";
}
@GetMapping("/updateUser/{id}")
public String updateList(@PathVariable("id") int id){
String sql = "update mybatis.user set name=?, pwd=? where id="+id;
//封装
Object[] objects = new Object[2];
objects[0] = "xiaoming";
objects[1] = "0000";
jdbcTemplate.update(sql,objects);
return "update-ok";
}
@GetMapping("/deleteUser/{id}")
public String deleteList(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id=?";
jdbcTemplate.update(sql, id);
return "delete-ok";
}
}
整合 Druid
1、配置 Druid
-
添加 Druid 数据源依赖
<!-- Druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency>
-
切换数据源:通过 spring.datasource.type 指定数据源
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver # 自定义数据源 type: com.alibaba.druid.pool.DruidDataSource
-
数据源切换之后,在测试类中注入 DataSource,获取并输出,输出结果为
class com.alibaba.druid.pool.DruidDataSource
,说明切换成功 -
切换成功之后,就可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数等设置项,可以查看源码
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.jdbc.Driver # 自定义数据源 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 的依赖
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
需要手动为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成,新建一个配置类 DruidConfig.class
@Configuration public class DruidConfig { /* 将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建 @ConfigurationProperties(prefix = "spring.datasource"):作用就是将全局配置文件中前缀为 spring.datasource 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中 */ @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource duridDataSource(){ return new DruidDataSource(); } }
-
测试
@SpringBootTestclass SpringbootDataJdbcApplicationTests { //DI注入数据源 @Autowired DataSource dataSource; @Test public void contextLoads() throws SQLException { //看一下默认数据源 System.out.println(dataSource.getClass()); //获得连接 Connection connection = dataSource.getConnection(); System.out.println(connection); DruidDataSource druidDataSource = (DruidDataSource) dataSource; System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive()); System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize()); //关闭连接 connection.close(); } }
-
输出设置的参数,说明配置生效
2、配置 Druid 数据源监控
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装路由器时,人家也提供了一个默认的 web 页面。
需要设置 Druid 的后台管理页面,比如登录账号、密码等配置,浏览器访问 :http://localhost:8080/druid/login.html,输入设置的账号和密码即可查看
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource duridDataSource(){
return new DruidDataSource();
}
// 配置 Druid 监控管理后台的Servlet
// 后台监控功能:web.xml,ServletRegistrationBean
// 因为SpringBoot内置了servlet容器,所以没有web.xml,替代方法:ServletRegistrationBean
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
// 后台需要有人登陆,账号密码设置
HashMap<String, String> initParameters = new HashMap<>();
// 增加配置,这些参数可以在 com.alibaba.druid.support.http.StatViewServlet
// 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
// 登陆的key是固定的loginUsername、loginPassword
initParameters.put("loginUsername", "admin");
initParameters.put("loginPassword", "123456");
// 允许谁可以访问,为空或者为null时,表示允许所有访问
initParameters.put("allow", "");
// 禁止谁能访问 initParameters.put("deny", "");
bean.setInitParameters(initParameters);//设置初始化参数
return bean;
}
3、配置 Druid web 监控 filter 过滤器
// web 监控的 filter
// WebStatFilter:用于配置 web和Druid数据源之间的管理关联监控统计
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
// 可以过滤哪些请求
Map<String, String> initParamters = new HashMap<>();
//exclusions:设置哪些请求进行过滤排除掉,这些东西不进行统计,
initParamters.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParamters);
//"/*" 表示过滤所有请求
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
整合 MyBatis
官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/dependency-info.html
-
创建测试项目,引入【Web】 Spring Web、【SQL】JDBC API、MySQL Driver 依赖
-
导入 MyBatis 所需要的依赖
<!-- mybatis-spring-boot-starter:整合 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>
-
配置数据库连接信息
spring.datasource.username=root spring.datasource.password=root spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.NonRegisteringDriver # 整合 MyBatis mybatis.type-aliases-package=com.song.pojo mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
-
测试数据库是否连接成功
@SpringBootTest class Springboot05MybatisApplicationTests { @Autowired DataSource dataSource; @Test void contextLoads() throws SQLException { System.out.println(dataSource.getClass()); System.out.println(dataSource.getConnection()); } }
-
创建实体类 User,导入 Lombok
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; }
-
创建 mapper 目录以及对应的 Mapper 接口 UserMapper.class
// 这个注解表示这是一个 mybatis 的 mapper类 dao @Mapper @Repository public interface UserMapper { List<User> queryUserList(); User queryUserById(); int addUser(User user); int UpdateUser(User user); int deleteUser(int id); }
-
对应的 Mapper 映射文件 UserMapper.xml(在 resources/mybatis/mapper 目录下,如果在 java 目录下需要配置静态资源过滤)
<?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.song.mapper.UserMapper"> <select id="queryUserList" resultType="User"> select * from User </select> <select id="queryUserById" resultType="User"> select * from User where id = #{id} </select> <insert id="addUser" parameterType="User"> insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd}) </insert> <update id="UpdateUser" parameterType="User"> update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id} </update> <delete id="deleteUser" parameterType="int"> delete from mybatis.user where id=#{id}; </delete> </mapper>
-
maven 配置资源过滤问题(当 UserMapper.xml 和 UserMapper.class 在同一个目录时需要配置)
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources>
-
编写 UserController 进行测试!
@RestController public class UserController { @Autowired private UserMapper userMapper; @GetMapping("/queryUserList") public List<User> queryUserList(){ List<User> userList = userMapper.queryUserList(); for (User user: userList) { System.out.println(user); } return userList; } //...增删改方法 }
-
启动项目访问进行测试