SpingBoot持久层开发原理
1. JDBC
SpringBoot关于数据库的配置都存在于org.springframework.boot.autoconfigure.jdbc
- 关于数据库的相关配置存放于
DataSourceProperties
中
@ConfigurationProperties(
prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
private String name;
private String driverClassName;
private String url;
private String username;
private String password;
private List<String> schema;
private String schemaUsername;
private String schemaPassword;
private List<String> data;
private String dataUsername;
private String dataPassword;
- 在实际使用的时候可以通过
spring.datasource
修改内部的属性
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.1.113:3308/jdbc
driver-class-name: com.mysql.jdbc.Driver
SpringBoot
通过DataSourceConfiguration
创建数据源,默认使用Hikari
连接池。可以通过spring.datasource.type
指定使用的数据源类型- 支持以下这四种数据源
通过spring.datasource.dbcp2
spring.datasource.hikari
spring.datasource.tomcat
来修改springboot提供的数据源的配置
2. 数据源自动配置原理
- 自动配置通过
DataSourceAutoConfigration
来完成对数据源的自动配置
- 通过内部类
PooledDataSourceConfiguration
类来实现自动配置- 导入了各个数据源。
Hikari.class
,Tomcat.class
…… - 每一个数据源刚好对应于
DataSourceConfiguration
类中的数据源对象
- 导入了各个数据源。
@Configuration(
proxyBeanMethods = false
)
@Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class})
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
@Import({Hikari.class, Tomcat.class, Dbcp2.class, Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {
protected PooledDataSourceConfiguration() {
}
}
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
3. 创建表
- SpringBoot支持直接运行建表语句和插入数据的SQL。通过
DataSourceInitializer
类的完成- 通过
runSchemaScripts()
运行建表语句 - 通过
runDataScripts()
运行插入数据的SQL语句
- 通过
- 默认可以通过在资源文件下添加SQL语句在服务器启动之时,运行建表语句和插入数据的语句
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.1.113:3308/jdbc
driver-class-name: com.mysql.cj.jdbc.Driver
initialization-mode: always //springBoot2.0以上需要添加
schema:
- classpath:employee.sql
- classpath:department.sql
- SpringBoot默认配置了
JdbcTemplate
class JdbcTemplateConfiguration {
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
4. 整合Druid
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
- 通过
spring.datasource.type
为druid
。并且配置druid连接源的参数
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
# 数据源其他配置
initialSize: 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,slf4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
- Druid常用配置
配置 | 缺省值 | 说明 |
---|---|---|
name | 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this) | |
initialSize | 0 | 初始化建立物理连接的个数,发生在init方法或者getConnection |
maxActive | 8 | 最大连接池的数量 |
maxIdle | 8 | 已经废弃 |
maxWait | 连接最大等待时间 | |
poolPreparedStatements | false | 是否缓存prepaerdStatement,也就是PSCache。游标使用 |
testOnBorrow | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testOnReturn | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 |
testWhileIdle | false | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
validationQuery | 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。 | |
maxOpenPreparedStatements | -1 | 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 |
timeBetweenEvictionRunsMillis | 有两个含义: 1) Destroy线程会检测连接的间隔时间2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 |
4.1 SpringBoot中使用Druid
SpringBoot默认不支持Druid所以需要将数据源添加到容器中
- 将DruidDataSource数据源添加到容器中,并且导入yml中的相关配置
//导入配置文件中的druid数据库的相关配置
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
4.2 SpringBoot使用Druid提供的数据库监控系统
- 创建访问该系统的Servlet。Druid提供了
StatViewServlet
作为该系统的Servlet。通过Springboot提供的自定义Servlet
创建
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
initParams.put("allow","");//允许谁访问,默认是所有的用户
// initParams.put("deny","192.168");//不允许谁访问
bean.setInitParameters(initParams);
return bean ;
}
- 添加一个过滤器作为监控器
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
filterRegistrationBean.setInitParameters(initParams);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
return filterRegistrationBean ;
}
4.3 测试
- 访问一个JDBC请求
- 访问Druid管理后台,里面显示了执行的SQL语句
5. 整合Mybatis
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
5.1 基于注解
- 通过
@Mapper
注解声明属于mybatis
@Mapper
@Repository("departmentMapper")
public interface IDepartmentMapper {
@Select("select * from department")
List<Department> findAll();
@Select("select * from department where id = #{id}")
Department findDepartById(Integer id );
@Options(useGeneratedKeys = true , keyColumn = "id" )
@Insert("insert into department(departmentName) values(#{departmentName})")
int insertDepart(Department department);
@Delete("delete from department where id = #{id}")
int deleteDepart(Integer id);
@Update("update department set departmentName = #{departmentName} where id = #{id}")
int updateDepart(Department department);
}
- 自定义MyBatis的配置规则;通过
ConfigurationCustomizer
来修改
@Configuration
public class MyBatisConfigurer {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return configuration->configuration.setMapUnderscoreToCamelCase(true);//设置驼峰命名
}
}
@MapperScan
指定需要扫描哪几个包,添加以后将相当于给包中的类添加了@Mapper
public @interface MapperScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
- 在运行的时候可会出现这样的警告。出现的原因是由于
JDK
版本太高了,需要1.8或者以下
5.2 基于配置文件
- 在资源文件下书写主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
开启自动驼峰命名规则(camel case)映射
</settings>
</configuration>
- 书写接口映射文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bywlstudio.springboot02.mapper.IDepartmentMapperXml">
<select id="findAll" resultType="com.bywlstudio.springboot02.bean.Department">
select * from department ;
</select>
<insert id="insertDepart" parameterType="com.bywlstudio.springboot02.bean.Department" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into department(departmentName) values(#{departmentName})
</insert>
</mapper>
- 在
yml
配置文件中配置
mybatis:
config-location: classpath:mapper/mapper.xml # 配置主配置文件
mapper-locations: classpath:mapper/deparment/DepartmentMapperXml.xml # 配置映射文件
- 项目结构