SpringBoot的数据访问

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 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
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
253 2
|
2月前
|
JSON JavaScript 前端开发
springboot中使用knife4j访问接口文档的一系列问题
本文作者是一位自学前端两年半的大一学生,分享了在Spring Boot项目中使用Knife4j遇到的问题及解决方案,包括解决Swagger请求404错误、JS错误等,详细介绍了依赖升级、注解替换及配置修改的方法。
150 1
|
2月前
|
SQL 前端开发 关系型数据库
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
68 9
|
2月前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
50 2
|
2月前
|
JSON JavaScript 前端开发
springboot中使用knife4j访问接口文档的一系列问题
本文介绍了在Spring Boot项目中使用Knife4j访问接口文档时遇到的一系列问题及其解决方案。作者首先介绍了自己是一名自学前端的大一学生,熟悉JavaScript和Vue,正在向全栈方向发展。接着详细说明了如何解决Swagger请求404错误,包括升级Knife4j依赖、替换Swagger 2注解为Swagger 3注解以及修改配置类中的代码。最后,针对报JS错误的问题,提供了删除消息转换器代码的解决方法。希望这些内容能对读者有所帮助。
341 5
|
3月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
91 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
2月前
|
存储 easyexcel Java
SpringBoot+EasyExcel轻松实现300万数据快速导出!
本文介绍了在项目开发中使用Apache POI进行数据导入导出的常见问题及解决方案。首先比较了HSSFWorkbook、XSSFWorkbook和SXSSFWorkbook三种传统POI版本的优缺点,然后根据数据量大小推荐了合适的使用场景。接着重点介绍了如何使用EasyExcel处理超百万数据的导入导出,包括分批查询、分批写入Excel、分批插入数据库等技术细节。通过测试,300万数据的导出用时约2分15秒,导入用时约91秒,展示了高效的数据处理能力。最后总结了公司现有做法的不足,并提出了改进方向。
|
4月前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
本文介绍了一个基于Spring Boot和Vue.js实现的在线考试系统。随着在线教育的发展,在线考试系统的重要性日益凸显。该系统不仅能提高教学效率,减轻教师负担,还为学生提供了灵活便捷的考试方式。技术栈包括Spring Boot、Vue.js、Element-UI等,支持多种角色登录,具备考试管理、题库管理、成绩查询等功能。系统采用前后端分离架构,具备高性能和扩展性,未来可进一步优化并引入AI技术提升智能化水平。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
|
4月前
|
Java 关系型数据库 MySQL
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和JSP技术的房屋租赁系统,旨在通过自动化和信息化手段提升房屋管理效率,优化租户体验。系统采用JDK 1.8、Maven 3.6、MySQL 8.0、JSP、Layui和Spring Boot 2.0等技术栈,实现了高效的房源管理和便捷的租户服务。通过该系统,房东可以轻松管理房源,租户可以快速找到合适的住所,双方都能享受数字化带来的便利。未来,系统将持续优化升级,提供更多完善的服务。
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)
|
4月前
|
Java Spring
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问
本文介绍了Spring Boot中静态资源的访问位置、如何进行静态资源访问测试、自定义静态资源路径和静态资源请求映射,以及如何处理自定义静态资源映射对index页面访问的影响。提供了两种解决方案:取消自定义静态资源映射或编写Controller来截获index.html的请求并重定向。
springboot静态资源目录访问,及自定义静态资源路径,index页面的访问