SpringBoot的数据访问
一、JDBC方式
- 引入starter。
<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>
- 配置application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.cj.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root
- 配置后默认使用org.apache.tomcat.jdbc.pool.DataSource作为数据源;数据源的相关配置都在org.springframework.boot.autoconfigure.jdbc.DataSourceProperties里面。
@ConfigurationProperties(
prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
private ClassLoader classLoader;
private String name;
private boolean generateUniqueName;
private Class<? extends DataSource> type;
private String driverClassName;
private String url;
private String username;
private String password;
private String jndiName;
private DataSourceInitializationMode initializationMode;
private String platform;
private List<String> schema;
private String schemaUsername;
private String schemaPassword;
private List<String> data;
private String dataUsername;
private String dataPassword;
private boolean continueOnError;
private String separator;
private Charset sqlScriptEncoding;
private EmbeddedDatabaseConnection embeddedDatabaseConnection;
private DataSourceProperties.Xa xa;
private String uniqueName;
.....
}
自动配置原理
根据org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration,根据配置去创建数据源,默认使用tomcat连接池。SpringBoot默认支持的数据源类型:
- "com.zaxxer.hikari.HikariDataSource",
- "org.apache.tomcat.jdbc.pool.DataSource",
- "org.apache.commons.dbcp2.BasicDataSource"
- 可以使用spring.datasource.type指定数据源类型。因为springboot在创建数据源的时候就是根据这个来选择要创建的数据源的类型的。
abstract class DataSourceConfiguration {
DataSourceConfiguration() {
}
protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
return properties.initializeDataSourceBuilder().type(type).build();
}
@Configuration
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"}
)
static class Generic {
Generic() {
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
@Configuration
@ConditionalOnClass({BasicDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "org.apache.commons.dbcp2.BasicDataSource",
matchIfMissing = true
)
static class Dbcp2 {
Dbcp2() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.dbcp2"
)
public BasicDataSource dataSource(DataSourceProperties properties) {
return (BasicDataSource)DataSourceConfiguration.createDataSource(properties, BasicDataSource.class);
}
}
@Configuration
@ConditionalOnClass({HikariDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true
)
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
public HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
@Configuration
@ConditionalOnClass({org.apache.tomcat.jdbc.pool.DataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
matchIfMissing = true
)
static class Tomcat {
Tomcat() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.tomcat"
)
public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class);
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
String validationQuery = databaseDriver.getValidationQuery();
if (validationQuery != null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
}
return dataSource;
}
}
}
- 自定义数据源类型。
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name="spring.datasource.type")
static class Generic{
@Bean
public DataSource dataSource(DataSourceProperties properties){
//使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并绑定相关属性
return properties.initializeDataSourceBuilder().build();
}
}
- 自动运行建表语句原理
自动运行建表语句依赖于org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer这个类,在应用启动的时候,会去寻找字段建表语句并运行。
class DataSourceInitializer {
private static final Log logger = LogFactory.getLog(DataSourceInitializer.class);
private final DataSource dataSource;
private final DataSourceProperties properties;
private final ResourceLoader resourceLoader;
DataSourceInitializer(DataSource dataSource, DataSourceProperties properties, ResourceLoader resourceLoader) {
this.dataSource = dataSource;
this.properties = properties;
this.resourceLoader = (ResourceLoader)(resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
}
DataSourceInitializer(DataSource dataSource, DataSourceProperties properties) {
this(dataSource, properties, (ResourceLoader)null);
}
public DataSource getDataSource() {
return this.dataSource;
}
public boolean createSchema() {
List<Resource> scripts = this.getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");
if (!scripts.isEmpty()) {
if (!this.isEnabled()) {
logger.debug("Initialization disabled (not running DDL scripts)");
return false;
}
String username = this.properties.getSchemaUsername();
String password = this.properties.getSchemaPassword();
this.runScripts(scripts, username, password);
}
return !scripts.isEmpty();
}
public void initSchema() {
List<Resource> scripts = this.getScripts("spring.datasource.data", this.properties.getData(), "data");
if (!scripts.isEmpty()) {
if (!this.isEnabled()) {
logger.debug("Initialization disabled (not running data scripts)");
return;
}
String username = this.properties.getDataUsername();
String password = this.properties.getDataPassword();
this.runScripts(scripts, username, password);
}
}
private boolean isEnabled() {
DataSourceInitializationMode mode = this.properties.getInitializationMode();
if (mode == DataSourceInitializationMode.NEVER) {
return false;
} else {
return mode != DataSourceInitializationMode.EMBEDDED || this.isEmbedded();
}
}
private boolean isEmbedded() {
try {
return EmbeddedDatabaseConnection.isEmbedded(this.dataSource);
} catch (Exception var2) {
logger.debug("Could not determine if datasource is embedded", var2);
return false;
}
}
//查找要自动运行的语句
private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) {
if (resources != null) {
return this.getResources(propertyName, resources, true);
} else {
String platform = this.properties.getPlatform();
List<String> fallbackResources = new ArrayList();
fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
fallbackResources.add("classpath*:" + fallback + ".sql");
return this.getResources(propertyName, fallbackResources, false);
}
}
//运行语句
private void runScripts(List<Resource> resources, String username, String password) {
if (!resources.isEmpty()) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(this.properties.isContinueOnError());
populator.setSeparator(this.properties.getSeparator());
if (this.properties.getSqlScriptEncoding() != null) {
populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());
}
Iterator var5 = resources.iterator();
while(var5.hasNext()) {
Resource resource = (Resource)var5.next();
populator.addScript(resource);
}
DataSource dataSource = this.dataSource;
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
dataSource = DataSourceBuilder.create(this.properties.getClassLoader()).driverClassName(this.properties.determineDriverClassName()).url(this.properties.determineUrl()).username(username).password(password).build();
}
DatabasePopulatorUtils.execute(populator, dataSource);
}
}
}
所以。如果ROM要初始化一些数据库脚本,可以按照规则,将要初始化的数据库脚本命名为schema-*.sql 、data-*.sql这种格式,比如schema.sql,sachema-all.sql等,也可以在配置文件中指定位置。
schema:
- classpath:department.sql
二、整合Druid数据源
- 引入druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
- 编写druid的配置类
//导入druid数据源
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置druid管理监控
//1.配置一个管理后台的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.12.34");
bean.setInitParameters(initParams);
return bean;
}
//2.配置一个web监控的filter
@Bean
public FilterRegistrationBean webStateFilter(){
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;
}
}
三、整合Mybatis
- 引入mybatis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mybaties</artifactId>
</dependency>
配置数据源属性(同上)
自定义MyBatis的配置规则
要想自定义mybatis的匹配规则只需要容器中添加一个ConfigurationCustomizer即可。
@Configuration
public class MyBatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomeizer(){
return new ConfigurationCustomizer(){
@Override
public void customize(Configuration configuration){
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
- 使用MapperScan批量扫描所有Mapper接口
@MapperScan(value="com.desperado.mapper")
@SpringBootApplication
public class ProjectDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ProjectDemoApplication.class, args);
}
}
- 使用配置文件扫描
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
四、整合SpringData JPA
- 编写一个实体类和数据表进行映射,并且配置好映射关系。
// 使用JPA注解配置映射关系
@Entity // 标识这是一个JPA的实体类(和数据表映射的类)
@Table(name = "tbl_user") // 指定和数据库对应的表,如果省略默认表名就是类名小写
public class User {
@Id // 标识这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//指定主键的生成方式
private Integer id;
@Column(name = "name",length = 50) //指定和数据表对应的列
private String name;
@Column // 如果忽略名称,那么需要字段名称和数据表字段名称一致
private String email;
}
- 编写一个Dao接口来操作实体类对应的数据表。
// 继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}
- 基本配置
# 更新或者创建数据表结构
spring.jpa.hibernate.ddl-auto=update
# 控制台显示sql
spring.jpa.hibernate.show-sql=true
SpringBoot的数据访问的更多相关文章
- 六、SpringBoot与数据访问
六.SpringBoot与数据访问 1.JDBC spring: datasource: username: root password: 123456 url: jdbc:mysql://192.1 ...
- SpringBoot之数据访问和事务-专题三
SpringBoot之数据访问和事务-专题三 四.数据访问 4.1.springboot整合使用JdbcTemplate 4.1.1 pom文件引入 <parent> <groupI ...
- java框架之SpringBoot(9)-数据访问及整合MyBatis
简介 对于数据访问层,无论是 SQL 还是 NOSQL,SpringBoot 默认采用整合 SpringData 的方式进行统一处理,添加了大量的自动配置,引入了各种 Template.Reposit ...
- SpringBoot 之数据访问
1. Spring Boot 与 JDBC 默认使用 org.apache.tomcat.jdbc.pool.DataSource 数据源; // application.yml spring: da ...
- SpringBoot(九) -- SpringBoot与数据访问
一.简介 对于数据访问层,无论是SQL还是NOSQL,Spring Boot默认采用整合Spring Data的方式进行统一处理,添加大量自动配置,屏蔽了很多设置.引入各种xxxTemplate,xx ...
- 10分钟进阶SpringBoot - 05. 数据访问之JDBC(附加源码分析+代码下载)
10分钟进阶SpringBoot - 05. 数据访问之JDBC 代码下载:https://github.com/Jackson0714/study-spring-boot.git 一.JDBC是什么 ...
- 20、Springboot 与数据访问(JDBC/自动配置)
简介: 对于数据访问层,无论是SQL还是NOSQL,Spring Boot默认采用整合 Spring Data的方式进行统一处理,添加大量自动配置,屏蔽了很多设置.引入 各种xxxTemplate,x ...
- SpringBoot与数据访问
pom依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- springboot与数据访问之jdbc
官网的starthttps://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter 添加依 ...
随机推荐
- Sql中truncate,delete以及drop的比较
相同点: 1.truncate和不带where子句的delete.以及drop都会删除表内的数据. 2.drop.truncate都是DDL语句(数据定义语言),执行后会自动提交. 不同点: 1. t ...
- [Scikit-learn] 2.3 Clustering - kmeans
参考: 2.3. Clustering 2.4. Biclustering 2.1.2.3. The Dirichlet Process Clusering, GMM, Variational Inf ...
- 图解 HTTP 笔记(六)——HTTP 首部
本章主要讲解了 HTTP 首部的结构,已经首部中各字段的用法. 一.HTTP 报文首部 上图是 HTTP 请求报文的结构. HTTP 请求报文由方法.URI.HTTP 版本.HTTP 首部字段等组成. ...
- PAT 甲级 1019 General Palindromic Number (进制转换,vector运用,一开始2个测试点没过)
1019 General Palindromic Number (20 分) A number that will be the same when it is written forwards ...
- 关于运维之故障复盘篇-Case Study
关于故障的事后复盘,英文名 Case Study是非常有必要做的,当然是根据故障的级别,不可能做到每个故障都Case Study,除非人员和时间充足: 文档能力也是能力的一种,一般工程师的文档能力比较 ...
- vs 扩展和更新下载的插件在什么位置呢,看看吧,哈哈
C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\10.0\Extensions,注意哈,这个AppData是隐藏的哟,要显示才能 ...
- QFramework 使用指南 2020(六):脚本生成(4)小结与补充
我们花了四篇文章,介绍了 QF 中的脚本生成功能. 实际上 QF 中的脚本生成是有两种的,第一种就是我们现在学习的 ViewController + Bind 模式. 这种模式是为除 UGUI 以外的 ...
- Mysql的binlog 和InnoDB的redo-log
来源:https://www.jianshu.com/p/4bcfffb27ed5 mysql日志系统之redo log和bin log Mr林_月生关注 12018.12.02 01:35:06字数 ...
- CentOS 7 利用qemu模拟ARM vexpress A9开发板
听说qemu用于仿真arm很不错,今日就来试了一把.由于刚刚开始,了解的并不多.本文仅仅记录Qemu装载Linux kernel和busybox根文件系统的过程.后续将会深入了解仿真的其他内容. 先上 ...
- python进程池 使用Queue实现计数功能
多进程中各个进程间相互隔离,进程间通信需要使用到通道. 多进程中使用Queue实现进程中通信 from multiprocessing import Process,Queue import time ...