在Spring Boot中如果需要访问数据库,我需要导入以下两个依赖:
<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>
之后在配置文件中配置好数据库:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.15.22:3306/jdbc
driver‐class‐name: com.mysql.jdbc.Driver
之后直接使用JdbcTemplate来操作数据库即可,默认是用org.apache.tomcat.jdbc.pool.DataSource作为数据源。那么这些是如何完成的呢?可以接着往下看。注意:我使用的是Spring Boot 2.1.7版本,不同版本可能源码有不同。
在Spring Boot的autoconfigure包下有一个叫jdbc的包,其中帮我们做好了数据库的配置,可以查看DataSourceConfiguration,根据配置创建数据源,默认使用Tomcat连接池;可以使用spring.datasource.type指定自定义的数据源类型,如果没有指定的话,就使用org.apache.tomcat.jdbc.pool.DataSource数据源了,默认支持org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource、BasicDataSource这些数据源。在该文件的最后还有这么一段:
/**
* Generic DataSource configuration.
*/
@Configuration
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
它的意思是,如果我们配置的spring.datasource.type不是上面任意一个数据源,就使用这种方式创建数据源,其原理是使用DataSourceBuilder创建数据源,利用反射创建type指定的数据源,并且绑定相关属性。此外,Spring Boot还可以帮我自动运行建表和数据创建.sql脚本。这又是如何实现的呢?接着往下看。
在jdbc包下还有一个DataSourceInitializerInvoker类,它继承了ApplicationListener,所以它是一个监听器,监听什么呢?这个类的注释中给出了解释:
/**
* Bean to handle {@link DataSource} initialization by running {@literal schema-*.sql} on
* {@link InitializingBean#afterPropertiesSet()} and {@literal data-*.sql} SQL scripts on
* a {@link DataSourceSchemaCreatedEvent}.
*
* @author Stephane Nicoll
* @see DataSourceAutoConfiguration
*/
也就是说,如果InitializingBean#afterPropertiesSet()发生时运行schema-.sql脚本,发生DataSourceSchemaCreatedEvent时运行data-.sql 脚本。所以如果当你需要在程序运行的时候建表,直接在classpate下创建schema-.sql建表文件即可。如果你还需要插入数据,直接在classpate下创建data-.sql插入数据文件即可。不过Spring Boot也支持你直接在数据库中声明schema文件的位置和名称,如:
Spring:
datasource:
schema:
‐ classpath:department.sql
最后需要注意的是,如果你在classpate下创建了schema-*.sql建表文件,那么每次启动程序都会运行这个脚本,所以当你不需要建表的时候,注意要及时删除。
最后,在JdbcTemplateAutoConfiguration文件还自动帮我创建好了JdbcTemplate,使用的时候直接自动注入即可:
@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource);
JdbcProperties.Template template = this.properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
以上就是Spring Boot默认的数据访问时的配置了。
在实际开发的时候,我们很少使用org.apache.tomcat.jdbc.pool.DataSource作为我们的数据源,这里我给出之前提到过的切换数据源的操作,这里我切换到druid数据源,这个数据源有很方便的监控的功能,读者可以作为参照。
首先我们需要在依赖中引入druid数据源:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
而后,指定我们的数据源类型,并且进行数据源的配置:
spring:
datasource:
# 数据源基本配置
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_crud
type: com.alibaba.druid.pool.DruidDataSource
# 数据源其他配置
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,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
这里需要注意的时,这里有很多属性的配置是无法自动配置到DataSourceProperties中的。也就无法被我们的druid数据源使用到,这里我们可以编写我们自己的配置类:
package com.chester.webdemo.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
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.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
//这个注解引入我们在上面yml文件中配置的参数到DruidDataSource数据源中
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid监控
//1.配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet());
Map<String, String> initParams = new HashMap<>();
//设置后台监控的登陆用户名
initParams.put("loginUsername", "admin");
//设置后台监控的登陆密码
initParams.put("loginPassword", "123456");
//设置允许访问的地址
initParams.put("allow", "");
//设置不允许访问的地址
initParams.put("deny", "192.168.15.21");
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;
}
}
如果这个数据源被注入到了容器中,上面说的org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource、BasicDataSource这些数据源就不会继续注入了,因为这些数据源在自动注入容器的时候有@ConditionalOnMissingBean(DataSource.class)这样一个注解。这个时候我们可以访问http://localhost:8081/druid 进入druid的监控界面,填入我们配置好的用户名,密码即可。
最后我们整合mybatis,首先我们需要引入mybatis:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
从名字中我们可以知道,这个包并非Spring官方出品,因为Spring的名字更像是这样spring‐boot‐starter‐*。这个包实际上是mybatis出的适配Spring Boot的。接下来的工作就很简单了,因为Spring Boot已经帮我配置好了,这里依旧给出使用mybatis的示例:
1. 首先创建实体类:
package com.chester.springboot.bean;
public class Department {
private Integer id;
private String departmentName;
public void setId(Integer id) {
this.id = id;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public String getDepartmentName() {
return departmentName;
}
}
2. 创建mapper
package com.chester.springboot.mapper;
import com.chester.springboot.bean.Department;
import org.apache.ibatis.annotations.*;
//指定这是一个操作数据库的mapper
@Mapper
public interface DepartmentMapper {
@Select("select * from department where id=#{id}")
public Department getDeptById(Integer id);
@Delete("delete from department where id=#{id}")
public int deleteDeptById(Integer id);
//Options的注解的意思是插入后将生成的id封装到department中,方便我们之后的使用
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into department(department_name) values(#{departmentName})")
public int insertDept(Department department);
@Update("update department set department_name=#{departmentName} where id=#{id}")
public int updateDept(Department department);
}
这里@Mapper也可以转换为直接在主类上写@MapperScan(value = “com.chester.springboot.mapper”)这个注解,这样一来com.chester.springboot.mapper这个包下的接口就会自动转换为mapper。
最后编写cotroller使用即可
package com.chester.springboot.controller;
import com.atguigu.springboot.bean.Department;
import com.atguigu.springboot.bean.Employee;
import com.atguigu.springboot.mapper.DepartmentMapper;
import com.atguigu.springboot.mapper.EmployeeMapper;
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;
@RestController
public class DeptController {
@Autowired
DepartmentMapper departmentMapper;
@GetMapping("/dept/{id}")
public Department getDepartment(@PathVariable("id") Integer id){
return departmentMapper.getDeptById(id);
}
@GetMapping("/dept")
public Department insertDept(Department department){
departmentMapper.insertDept(department);
return department;
}
}
最后如果我们希望可以对MyBatis做一些自定义的配置,我们可以像下面这样写一个自动配置类,这里以开启驼峰命名法为例,或者直接在配置文件中配置:
package com.chester.springboot.config;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
@Configuration
public class MyBatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return new ConfigurationCustomizer(){
@Override
public void customize(Configuration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
总结:
在上面的描述中我们讨论了Spring Boot的数据源的自动配置原理,以及自动执行.sql的原理,我们还讲到如何将数据源切换到druid,并做好配置,最后我们还讲述了如何利用注解使用mybatis。