[TOC]
#
ⅠJDBC
一:添加依赖
1
2
3
4
5
6
7
8
9
<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>
二:配置
1
2
3
4
5
6
7
8
9
10
11
server:
port: 8080
spring:
application:
name: boot-jdbc
datasource:
username: root
password: 1230
url: jdbc:mysql://liqingfeng.com:3306/springboot?useSSL=false
driver-class-name: com.mysql.jdbc.Driver
二:自动配置原理
-
自动配置类:
DataSourceAutoConfiguration Properties类:DataSourcePropertiesjdbctemplate自动配置类:JdbcTemplateAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DataSourceInitializer dataSourceInitializer(DataSourceProperties
properties,
ApplicationContext applicationContext) {
return new DataSourceInitializer(properties, applicationContext);
}
这里是数据源自动配置类注入容器的一些组件,接下来我们就看看这些组件都起到了什么作用
DataSourceProperties
1
@EnableConfigurationProperties(DataSourceProperties.class)
导入配置属性类,就不多说了
Registrar
1
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static class Registrar implements ImportBeanDefinitionRegistrar {
private static final String BEAN_NAME = "dataSourceInitializerPostProcessor";
@Override
public void registerBeanDefinitions(AnnotationMetadata
importingClassMetadata,
BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(BEAN_NAME)) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(DataSourceInitializerPostProcessor.class);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// We don't need this one to be post processed otherwise it can cause a
// cascade of bean instantiation that we would rather avoid.
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
}
}
}
Registrar 类实现了 ImportBeanDefinitionRegistrar ,实现了 registerBeanDefinitions 主要作用是在容器中添加 DataSourceInitializerPostProcessor 类
1
2
3
4
5
6
7
8
9
10
class DataSourceInitializerPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof DataSource) {
// force initialization of this bean as soon as we see a DataSource
this.beanFactory.getBean(DataSourceInitializer.class);
}
return bean;
}
DataSourceInitializerPostProcessor 类主要是把容器中的所有 DataSource 类型的组件强制初始化
DataSourcePoolMetadataProvidersConfiguration
1
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
由 DataSourcePoolMetadataProvidersConfiguration 代码可以看出这个类主要是向容器中注入注入数据源,
由此也可以看出spring boot默认支持的连接池有 org.apache.tomcat.jdbc.pool.DataSource (默认)、HikariDataSource、org.apache.commons.dbcp.BasicDataSource、org.apache.commons.dbcp2.BasicDataSource 、自定义数据源 ,可以使用 spring boot 的 spring.datasource.type 配置修改数据源的类型
DataSourceInitializer
1
2
3
4
5
6
7
@Bean
@ConditionalOnMissingBean
public DataSourceInitializer dataSourceInitializer(DataSourceProperties
properties,
ApplicationContext applicationContext) {
return new DataSourceInitializer(properties, applicationContext);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> {
@PostConstruct
public void init() {
if (!this.properties.isInitialize()) {
logger.debug("Initialization disabled (not running DDL scripts)");
return;
}
if (this.applicationContext.getBeanNamesForType(DataSource.class, false,
false).length > 0) {
this.dataSource = this.applicationContext.getBean(DataSource.class);
}
if (this.dataSource == null) {
logger.debug("No DataSource found so not initializing");
return;
}
runSchemaScripts();
}
@Override
public void onApplicationEvent(DataSourceInitializedEvent event) {
if (!this.properties.isInitialize()) {
logger.debug("Initialization disabled (not running data scripts)");
return;
}
// NOTE the event can happen more than once and
// the event datasource is not used here
if (!this.initialized) {
runDataScripts();
this.initialized = true;
}
}
DataSourceInitializer 实现了 ApplicationListener 接口,实现了 onApplicationEvent 方法,该方法中
runDataScripts() 初始化所有 classpath 目录下 data.sql 、data-all.sql脚本和配置文件中配置的 spring.datasource.data 的脚本
该类中还有一个 init 方法,标注了 @PostConstruct 注解,该注解是 JRS250 规范的注解就相当于spring中创建bean时指定的 init-method 方法(构造器之后)
Ⅰ:druid 配置
一:添加依赖
1
2
3
4
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
二:属性配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
spring:
application:
name: boot-jdbc
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql://liqingfeng.com:3306/springboot?useSSL=false
username: root
password: 1230
initial-size: 1
min-idle: 1
max-active: 5
max-wait: 3000
use-unfair-lock: true
time-between-eviction-runs-millis: 10000
min-evictable-idle-time-millis: 30000
validation-query: select '1'
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
use-global-data-source-stat: true
max-pool-prepared-statement-per-connection-size: 10
filters: stat,wall,slf4j
pool-prepared-statements: true
这里的
filters一定要配置,否则druid的SQL不能生效
三:让配置的属性生效
1
2
3
4
5
@ConfigurationProperties(prefix = "spring.druid")
@Bean
public DruidDataSource druidDataSource(){
return new DruidDataSource();
}
主要是添加
@ConfigurationProperties注解
四:配置 druid 监控
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean servletRegistrationBean = new
ServletRegistrationBean(new StatViewServlet(),"/druid/*");
Map<String,String> initParams = new HashMap<String,String>(6);
initParams.put("loginUsername","admin");
initParams.put("loginPassword","admin");
initParams.put("allow","");
servletRegistrationBean.setInitParameters(initParams);
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean filterRegistrationBean = new
FilterRegistrationBean(new WebStatFilter());
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("sessionStatEnable","true");
filterRegistrationBean.addInitParameter("profileEnable","true");
filterRegistrationBean.addInitParameter("principalCookieName","USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName","USER_SESSION");
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
配置
StatViewServlet和WebStatFilter
Ⅲ:整合 Mybatis
其实注解版什么都不需要配置,只需要在接口上添加 @Mapper 注解,然后写接口,在接口上加注解,并写对应的 SQL 语句就可以了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import com.feng.boot.mybatis.bean.Department;
import org.apache.ibatis.annotations.*;
/**
* @author Lee
*/
@Mapper
public interface DepartmentMapper {
/**
* 根据 ID 查询 Department
* @param id
* @return
*/
@Select("select * from department d where d.id = #{id}")
Department getDeptById(Integer id);
/**
* 根据 ID 删除 Department
* @param dId
* @return
*/
@Delete("delete from department d where d.id = #{id}")
int deleteDepartment(Integer dId);;
/**
* 插入 Department
* @param department
* @return
*/
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into department(departmentName) value (#{departmentName})")
int insertDepartment(Department department);
/**
* 更新 departmentName
* @param department
* @return
*/
@Update("update department d set d.departmentName = ${departmentName} where d.id
= ${id}")
int updateSelective(Department department);
}
1
@Options(useGeneratedKeys = true,keyProperty = "id")
是为了返回插入数据库中的记录的主键
若在 Mapper 接口上不使用 @Mapper 标注,则需要在 mybatis 配置类上添加 @MapperScan 注解并指定 Mapper 接口所在包
1
2
3
@MapperScan(basePackages = {"com.feng.boot.mybatis.mapper"})
@Configuration
public class MybatisConfig {
使用配置文件 配置 mybatis 常用配置
1
2
mybatis.mapper-locations=com.feng.boot.mapper
mybatis.config-location=classpath:mybatis-config.xml
使用自定义配置 配置 mybatis 常用配置
1
2
3
4
5
6
7
8
9
10
11
@MapperScan(basePackages = {"com.feng.boot.mybatis.mapper"})
@Configuration
public class MybatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return (customizer) -> {
customizer.setMapUnderscoreToCamelCase(true);
};
}
}
mybatis 全局配置文件和 mapper 配置文件使用

1
2
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.config-location=classpath:mybatis/mybatis-config.xml
Ⅳ:整合 JPA
当然整合 JPA 是在已经配置好了数据源的前提下,我们这里就不展示数据源的配置了

一:添加依赖
pom.xml
1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
二:配置 jpa 和 hibernate
1
2
3
4
5
jpa:
show-sql: true
hibernate:
ddl-auto: update
dialect: org.hibernate.dialect.MySQL57InnoDBDial
三:配置 jpa 扫描实体类包
1
2
3
4
@EntityScan(basePackages = {"com.feng.boot.datajpa.entity"})
@Configuration
public class DataJpaConfig {
}
四:编写实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
@Table(name = "tbl_user")
@Data
@Accessors(chain = true)
public class User implements Serializable {
private static final long serialVersionUID = 5467023455095967635L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String userName;
private Integer age;
}
五:编写 Repository 接口
1
2
3
public interface UserRepository extends JpaRepository<User, Integer> {
User getUserById(Integer id);
}