SpringBoot的数据访问

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 介绍SpringBoot的数据访问

一、JDBC方式

  1. 引入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>
  1. 配置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
  1. 配置后默认使用org.apache.tomcat.jdbc.pool.DataSource作为数据源;数据源的相关配置都在org.springframework.boot.autoconfigure.jdbc.DataSourceProperties里面。
@ConfigurationProperties(
prefix="spring.datasource")
publicclassDataSourcePropertiesimplementsBeanClassLoaderAware, InitializingBean {
privateClassLoaderclassLoader;
privateStringname;
privatebooleangenerateUniqueName;
privateClass<?extendsDataSource>type;
privateStringdriverClassName;
privateStringurl;
privateStringusername;
privateStringpassword;
privateStringjndiName;
privateDataSourceInitializationModeinitializationMode;
privateStringplatform;
privateList<String>schema;
privateStringschemaUsername;
privateStringschemaPassword;
privateList<String>data;
privateStringdataUsername;
privateStringdataPassword;
privatebooleancontinueOnError;
privateStringseparator;
privateCharsetsqlScriptEncoding;
privateEmbeddedDatabaseConnectionembeddedDatabaseConnection;
privateDataSourceProperties.Xaxa;
privateStringuniqueName;
.....
}
  1. 自动配置原理
    根据org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration,根据配置去创建数据源,默认使用tomcat连接池。
  2. SpringBoot默认支持的数据源类型:
  • "com.zaxxer.hikari.HikariDataSource",
  • "org.apache.tomcat.jdbc.pool.DataSource",
  • "org.apache.commons.dbcp2.BasicDataSource"
  1. 可以使用spring.datasource.type指定数据源类型。因为springboot在创建数据源的时候就是根据这个来选择要创建的数据源的类型的。
abstractclassDataSourceConfiguration {
DataSourceConfiguration() {
    }
protectedstatic<T>TcreateDataSource(DataSourcePropertiesproperties, Class<?extendsDataSource>type) {
returnproperties.initializeDataSourceBuilder().type(type).build();
    }
@Configuration@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name= {"spring.datasource.type"}
    )
staticclassGeneric {
Generic() {
        }
@BeanpublicDataSourcedataSource(DataSourcePropertiesproperties) {
returnproperties.initializeDataSourceBuilder().build();
        }
    }
@Configuration@ConditionalOnClass({BasicDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name= {"spring.datasource.type"},
havingValue="org.apache.commons.dbcp2.BasicDataSource",
matchIfMissing=true    )
staticclassDbcp2 {
Dbcp2() {
        }
@Bean@ConfigurationProperties(
prefix="spring.datasource.dbcp2"        )
publicBasicDataSourcedataSource(DataSourcePropertiesproperties) {
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    )
staticclassHikari {
Hikari() {
        }
@Bean@ConfigurationProperties(
prefix="spring.datasource.hikari"        )
publicHikariDataSourcedataSource(DataSourcePropertiesproperties) {
HikariDataSourcedataSource= (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
            }
returndataSource;
        }
    }
@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    )
staticclassTomcat {
Tomcat() {
        }
@Bean@ConfigurationProperties(
prefix="spring.datasource.tomcat"        )
publicorg.apache.tomcat.jdbc.pool.DataSourcedataSource(DataSourcePropertiesproperties) {
org.apache.tomcat.jdbc.pool.DataSourcedataSource= (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class);
DatabaseDriverdatabaseDriver=DatabaseDriver.fromJdbcUrl(properties.determineUrl());
StringvalidationQuery=databaseDriver.getValidationQuery();
if (validationQuery!=null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
            }
returndataSource;
        }
    }
}
  1. 自定义数据源类型。
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name="spring.datasource.type")
staticclassGeneric{
@BeanpublicDataSourcedataSource(DataSourcePropertiesproperties){
//使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并绑定相关属性returnproperties.initializeDataSourceBuilder().build();
        }
    }
  1. 自动运行建表语句原理
    自动运行建表语句依赖于org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer这个类,在应用启动的时候,会去寻找字段建表语句并运行。
classDataSourceInitializer {
privatestaticfinalLoglogger=LogFactory.getLog(DataSourceInitializer.class);
privatefinalDataSourcedataSource;
privatefinalDataSourcePropertiesproperties;
privatefinalResourceLoaderresourceLoader;
DataSourceInitializer(DataSourcedataSource, DataSourcePropertiesproperties, ResourceLoaderresourceLoader) {
this.dataSource=dataSource;
this.properties=properties;
this.resourceLoader= (ResourceLoader)(resourceLoader!=null?resourceLoader : newDefaultResourceLoader());
    }
DataSourceInitializer(DataSourcedataSource, DataSourcePropertiesproperties) {
this(dataSource, properties, (ResourceLoader)null);
    }
publicDataSourcegetDataSource() {
returnthis.dataSource;
    }
publicbooleancreateSchema() {
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)");
returnfalse;
            }
Stringusername=this.properties.getSchemaUsername();
Stringpassword=this.properties.getSchemaPassword();
this.runScripts(scripts, username, password);
        }
return!scripts.isEmpty();
    }
publicvoidinitSchema() {
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;
            }
Stringusername=this.properties.getDataUsername();
Stringpassword=this.properties.getDataPassword();
this.runScripts(scripts, username, password);
        }
    }
privatebooleanisEnabled() {
DataSourceInitializationModemode=this.properties.getInitializationMode();
if (mode==DataSourceInitializationMode.NEVER) {
returnfalse;
        } else {
returnmode!=DataSourceInitializationMode.EMBEDDED||this.isEmbedded();
        }
    }
privatebooleanisEmbedded() {
try {
returnEmbeddedDatabaseConnection.isEmbedded(this.dataSource);
        } catch (Exceptionvar2) {
logger.debug("Could not determine if datasource is embedded", var2);
returnfalse;
        }
    }
//查找要自动运行的语句privateList<Resource>getScripts(StringpropertyName, List<String>resources, Stringfallback) {
if (resources!=null) {
returnthis.getResources(propertyName, resources, true);
        } else {
Stringplatform=this.properties.getPlatform();
List<String>fallbackResources=newArrayList();
fallbackResources.add("classpath*:"+fallback+"-"+platform+".sql");
fallbackResources.add("classpath*:"+fallback+".sql");
returnthis.getResources(propertyName, fallbackResources, false);
        }
    }
//运行语句privatevoidrunScripts(List<Resource>resources, Stringusername, Stringpassword) {
if (!resources.isEmpty()) {
ResourceDatabasePopulatorpopulator=newResourceDatabasePopulator();
populator.setContinueOnError(this.properties.isContinueOnError());
populator.setSeparator(this.properties.getSeparator());
if (this.properties.getSqlScriptEncoding() !=null) {
populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());
            }
Iteratorvar5=resources.iterator();
while(var5.hasNext()) {
Resourceresource= (Resource)var5.next();
populator.addScript(resource);
            }
DataSourcedataSource=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数据源

  1. 引入druid依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency>
  1. 编写druid的配置类
//导入druid数据源@ConfigurationpublicclassDruidConfig {
@ConfigurationProperties(prefix="spring.datasource")
@BeanpublicDataSourcedruid(){
returnnewDruidDataSource();
    }
//配置druid管理监控//1.配置一个管理后台的Servlet@BeanpublicServletRegistrationBeanstatViewServlet(){
ServletRegistrationBeanbean=newServletRegistrationBean(
newStatViewServlet(),"/druid/*"        );
Map<String,String>initParams=newHashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
//允许所有访问initParams.put("allow","");
initParams.put("deny","192.168.12.34");
bean.setInitParameters(initParams);
returnbean;
    }
//2.配置一个web监控的filter@BeanpublicFilterRegistrationBeanwebStateFilter(){
FilterRegistrationBeanbean=newFilterRegistrationBean();
bean.setFilter(newWebStatFilter());
Map<String,String>initParams=newHashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
returnbean;
    }
}

三、整合Mybatis

  1. 引入mybatis依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mybaties</artifactId></dependency>
  1. 配置数据源属性(同上)
  2. 自定义MyBatis的配置规则
    要想自定义mybatis的匹配规则只需要容器中添加一个ConfigurationCustomizer即可。
@ConfigurationpublicclassMyBatisConfig {
@BeanpublicConfigurationCustomizerconfigurationCustomeizer(){
returnnewConfigurationCustomizer(){
@Overridepublicvoidcustomize(Configurationconfiguration){
configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}
  1. 使用MapperScan批量扫描所有Mapper接口
@MapperScan(value="com.desperado.mapper")
@SpringBootApplicationpublicclassProjectDemoApplication {
publicstaticvoidmain(String[] args) {
SpringApplication.run(ProjectDemoApplication.class, args);
 }
}
  1. 使用配置文件扫描
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

四、整合SpringData JPA

11.png

  1. 编写一个实体类和数据表进行映射,并且配置好映射关系。
// 使用JPA注解配置映射关系@Entity// 标识这是一个JPA的实体类(和数据表映射的类)@Table(name="tbl_user")  // 指定和数据库对应的表,如果省略默认表名就是类名小写publicclassUser {
@Id// 标识这是一个主键@GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键的生成方式privateIntegerid;
@Column(name="name",length=50) //指定和数据表对应的列privateStringname;
@Column// 如果忽略名称,那么需要字段名称和数据表字段名称一致privateStringemail;
}
  1. 编写一个Dao接口来操作实体类对应的数据表。
// 继承JpaRepository来完成对数据库的操作publicinterfaceUserRepositoryextendsJpaRepository<User,Integer> {
}
  1. 基本配置
# 更新或者创建数据表结构
spring.jpa.hibernate.ddl-auto=update
# 控制台显示sql
spring.jpa.hibernate.show-sql=true
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
20天前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
159 3
|
7月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——封装统一返回的数据结构
本文介绍了在Spring Boot中封装统一返回的数据结构的方法。通过定义一个泛型类`JsonResult&lt;T&gt;`,包含数据、状态码和提示信息三个属性,满足不同场景下的JSON返回需求。例如,无数据返回时可设置默认状态码&quot;0&quot;和消息&quot;操作成功!&quot;,有数据返回时也可自定义状态码和消息。同时,文章展示了如何在Controller中使用该结构,通过具体示例(如用户信息、列表和Map)说明其灵活性与便捷性。最后总结了Spring Boot中JSON数据返回的配置与实际项目中的应用技巧。
607 0
|
7月前
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 &quot;&quot;,Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
367 0
|
7月前
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——Spring Boot 默认对Json的处理
本文介绍了在Spring Boot中返回Json数据的方法及数据封装技巧。通过使用`@RestController`注解,可以轻松实现接口返回Json格式的数据,默认使用的Json解析框架是Jackson。文章详细讲解了如何处理不同数据类型(如类对象、List、Map)的Json转换,并提供了自定义配置以应对null值问题。此外,还对比了Jackson与阿里巴巴FastJson的特点,以及如何在项目中引入和配置FastJson,解决null值转换和中文乱码等问题。
1097 0
|
3月前
|
JSON Java 数据格式
Spring Boot返回Json数据及数据封装
在Spring Boot中,接口间及前后端的数据传输通常使用JSON格式。通过@RestController注解,可轻松实现Controller返回JSON数据。该注解是Spring Boot新增的组合注解,结合了@Controller和@ResponseBody的功能,默认将返回值转换为JSON格式。Spring Boot底层默认采用Jackson作为JSON解析框架,并通过spring-boot-starter-json依赖集成了相关库,包括jackson-databind、jackson-datatype-jdk8等常用模块,简化了开发者对依赖的手动管理。
451 3
|
9月前
|
前端开发 Java API
SpringBoot整合Flowable【06】- 查询历史数据
本文介绍了Flowable工作流引擎中历史数据的查询与管理。首先回顾了流程变量的应用场景及其局限性,引出表单在灵活定制流程中的重要性。接着详细讲解了如何通过Flowable的历史服务API查询用户的历史绩效数据,包括启动流程、执行任务和查询历史记录的具体步骤,并展示了如何将查询结果封装为更易理解的对象返回。最后总结了Flowable提供的丰富API及其灵活性,为后续学习驳回功能做了铺垫。
693 0
SpringBoot整合Flowable【06】- 查询历史数据
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
832 2
|
7月前
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
8月前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
2081 45
|
9月前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
2305 17
Spring Boot 两种部署到服务器的方式