博客中涉及到的代码仓库地址:demo-springBoot
SpringBoot对与数据访问层,做了大量的适配,无论是SQL还是NOSQL都支持,Spring Boot默认采用Spring Data对数据访问进行统一处理,包含的量的自动化配置,帮我们省去很多配置工作。
(一)JDBC访问
导入相关的Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
配置数据库连接相关内容
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/base_crud?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
书写测试类查看数据库连接情况
@SpringBootTest
class Springboot05JdbcApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println("数据源为:"+dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("获取到的数据库连接为:"+connection);
connection.close();
}
}
测试的结论:
- 默认使用
com.zaxxer.hikari.HikariDataSource作为数据源; - 数据源相关的配置在
DataSourceProperties中;
Springboot对JDBC的自动配置原理:
① 自动配置所在的包:org.springframework.boot.autoconfigure.jdbc
② DataSourceConfiguration 此类用于配置数据源,默认使用 HikariDataSource 作为数据源使用。使用 spring.datasource.type 配置数据源;
SpringBoot中默认支持的数据源:
org.apache.tomcat.jdbc.pool.DataSourcecom.zaxxer.hikari.HikariDataSourceorg.apache.commons.dbcp2.BasicDataSource
③ SpringBoot同样支持自定义数据源
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
DataSource dataSource(DataSourceProperties properties) {
// 使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并且绑定相关属性
return properties.initializeDataSourceBuilder().build();
}
}
④ 自动配置类 DataSourceAutoConfiguration 中导入了 DataSourceInitializationConfiguration 类用于初始化DataSource数据源配置;
⑤ 自动配置类中还配置了 JDBCTemplate 操作数据库;
(二)整合Druid数据源
Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含ProxyDriver,一系列内置的JDBC组件库,SQLParser等。Druid支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQLServer、H2等等。
Druid针对Oracle和MySql做了特别优化,比如Oracle的PSCache内存占用优化,MySql的ping检测优化。 Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等。
将数据源更改为Druid数据源操作:
① 导入Druid依赖;
② 修改配置文件,添加连接配置;
③ 书写配置类,配置Druid;
① 导入Druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
② 修改配置文件,添加配置项
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://139.224.83.90:3306/base_crud?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
# 使用DruidSource数据源
type: com.alibaba.druid.pool.DruidDataSource
# 数据源连接配置相关
# 初始化大小,最小,最大
initialSize: 5
minIdle: 5
maxActive: 20
# 配置获取连接等待超时时间
maxWait: 60000
# 配置检测间隔时间,检测会关闭空闲连接,单位时是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在连接池中最小存活时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 用来检测连接是否为有效SQL,必须为一个查询语句
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
# 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
testOnBorrow: false
# 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
testOnReturn: false
# 是否缓存preparedStatement,mysql5.5+建议开启
poolPreparedStatements: true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall
# 指定每个连接上PSCahe的大小
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
③ 书写配置类配置Druid
@Configuration
public class DruidConfig {
/**
* 导入数据源
* @return
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid() {
return new DruidDataSource();
}
/**
* 配置Durid监控
* 1.配置一个管理监控后台的Servlet
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet() {
// 创建后台Servlet并指定路径
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
// 配置Druid访问用户名和密码
initParams.put("loginUsername","admin");
initParams.put("loginPassword", "123456");
// 不配置则表示允许所有访问
initParams.put("allow","");
// 配置禁止访问的IP,与allow同时配置时,deny优先生效
initParams.put("deny","139.244.83.90");
bean.setInitParameters(initParams);
return bean;
}
/**
* 2.配置一个web监控的filter
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter() {
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;
}
}
更多关于Druid配置项的信息请参考: DruidDataSource配置属性列表
启动SpringBoot项目后,输入 http://localhost:9080/druid/ 输入配置好的用户名和密码,即可在浏览器查看Druid监控面板。
不同的数据库连接池连接速度对比:数据库连接池性能比对(hikari druid c3p0 dbcp jdbc)
(三)整合Mybatis框架
关于MyBatis框架的介绍和使用请参考前文博客:Mybatis框架 ,此处仅书写Mybatis框架和SpringBoot整合。
整合MyBatis框架的步骤:
① 导入MyBatis对SpringBoot的整合依赖;
② 配置数据库连接属性和数据源信息;
④ 使用MyBatis(注解/外部文件);
① 导入MyBatis对SpringBoot的整合依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- 导入Druid依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
mybatis-spring-boot-starter依赖构成
由上面的依赖关系图可知
mybatis-spring-boot-starter已经加入了JDBC依赖因此,我们无需再导入JDBC相关的依赖
② 配置数据库连接属性和数据源信息;
此处的配置信息与整合Druid数据源时的配置相同,此处不再展示
1. 注解使用MyBatis
通过注解使用MyBatis框架,直接在注解中书写SQL语句即可自动配置查询和对应。
@Mapper
public interface IUserDao {
/**
* 查询全部用户
* @return
*/
@Select("select * from user")
List<User> getUsers();
/**
* 查询单个用户
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User getUserById(Integer id);
/**
* 删除单个用户
* @param id
* @return
*/
@Delete("delete from user where id=#{id}")
Integer deleteUserById(Integer id);
/**
* 插入一个用户
* @param user
* @return
*/
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into user (username, birthday, sex, address) values (#{username}, #{birthday}, #{sex}, #{address})")
Integer saveUser(User user);
}
注解能够直接使用的原因:
SpringBoot进行了自动配置,通过 MybatisAutoConfiguration 类进行自动配置,具体的配置在配置属性类 MybatisProperties 中定义。
实现 ConfigurationCustomizer 接口可以自定义配置MyBatis
@org.springframework.context.annotation.Configuration
public class MybatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return new ConfigurationCustomizer() {
@Override
public void customize(Configuration configuration) {
// 配置允许驼峰命名转化,即驼峰命名和下划线命名转化
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
我们也可以在主启动类中书写 @MapperScan 注解用于批量扫描mapper,省去我们在每个Dao层的类书写 @Mapper 注解
@MapperScan(value = "cn.bruce.springboot.dao")
@SpringBootApplication
public class Springboot05MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot05MybatisApplication.class, args);
}
}
2. 通过外部文件配置mapper使用Mybatis
基本步骤:
① 书写dao层接口;
② 编写mapper配置文件;
③ 书写配置文件配置MyBatis;
④ 全局配置文件中指定配置文件路径;
① 书写dao层接口 IAccountDao
public interface IAccountDao {
/**
* 根据id获取账户信息
* @param id
* @return
*/
Account getAccountById(Integer id);
/**
* 获取全部账户
* @return
*/
List<Account> getAccounts();
/**
* 保存账户
* @param account
*/
void saveAccount(Account account);
/**
* 根据id删除账户
* @param id
*/
void deleteAccountById(Integer id);
/**
* 更新账户
* @param account
*/
void updateAccount(Account account);
}
② 书写外置配置文件 IAccount.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bruce.springboot.dao.IAccountDao">
<!-- 根据id获取账户信息 -->
<select id="getAccountById" resultType="cn.bruce.springboot.domain.Account">
select * from account where ID = #{id}
</select>
<!-- 获取全部账户 -->
<select id="getAccounts" parameterType="java.lang.Integer" resultType="cn.bruce.springboot.domain.Account">
select * from account
</select>
<!-- 保存账户信息 -->
<insert id="saveAccount" parameterType="cn.bruce.springboot.domain.Account">
insert into account(id, uid, money) value (#{id}, #{uid}, #{money})
</insert>
<!-- 根据id删除用户 -->
<select id="deleteAccountById" parameterType="java.lang.Integer">
delete from account where ID = #{id}
</select>
<!-- 更新账户信息 -->
<update id="updateAccount" parameterType="cn.bruce.springboot.domain.Account">
update account set ID = #{id}, UID = #{uid}, MONEY = #{money}
</update>
</mapper>
③ 使用外部文件 mybatis-config.xml 配置MyBatis
<?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"/>
</settings>
</configuration>
④ 在全局配置文件 application.yml 中指定mapper和配置文件位置
# mybatis相关的配置
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
注解和配置文件可以同时使用,简单的SQL查询使用注解,复杂的SQL查询使用外置的mapper。建议将所有的SQL查询都书写到mapper中便于统一管理。
(四)整合SpringData JPA
1. SpringData 简介
SpringData是Spring官方推出的用于统一数据访问的技术,提供对各种数据源的访问,以简化开发者的工作,同时SpringData中包含很多子项目用于实现不同数据源的访问。
1.1 Spring官网对SpringData的介绍
Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store.
It makes it easy to use data access technologies, relational and non-relational databases, map-reduce frameworks, and cloud-based data services. This is an umbrella project which contains many subprojects that are specific to a given database. The projects are developed by working together with many of the companies and developers that are behind these exciting technologies.
Spring Data的任务是为数据访问提供一个熟悉的、一致的、基于Spring的编程模型,同时仍然保留底层数据存储的特殊特性。
它使得数据访问技术、关系型和非关系型数据库、map-reduce框架和基于云的数据服务的使用更加容易。这是一个包含许多特定于给定数据库的子项目的伞形项目。这些项目是通过与支持这些令人兴奋的技术的许多公司和开发人员合作开发的。
SpringData中包含的子项目:
- SpringData JDBC
- SpringData JPA
- SpringData MongoDB
- SpringData Redis
- SpringData Neo4j
- ......
SpringData数据访问示意图
1.2 SpringData的特性:
SpringData为我们提供使用统一的API来对数据访问层进行操作;这主要是Spring Data Commons项目来实现的。Spring Data Commons让我们在使用关系型或者非关系型数据访问技术时都基于Spring提供的统一标准,标准包含了CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。
① SpringData提供统一的数据访问接口Repository接口:
Repository<T, ID extends Serializable>:统一接口
RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>>:基于乐观锁机制
CrudRepository<T, ID extends Serializable>:基本CRUD操作
PagingAndSortingRepository<T, ID extends Serializable>:基本CRUD及分页
② SpringData提供数据访问的模板类 xxxTemplate
如:MongoDBTemplate,RedisTemplate等用于操作数据访问
2. 整合使用SpringData JPA
2.1 SpringData JPA简介
SpringData JPA是基于JSR317规范实现的的JPA框架。JPA是(Java Persistence API)的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
SpringData官网中对SpringDataJPA的介绍
Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.
Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that’s actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.
Spring Data JPA是更大的Spring数据家族的一部分,它使得实现基于JPA的存储库变得很容易。该模块处理对基于JPA的数据访问层的增强支持。它使得构建使用数据访问技术的spring驱动的应用程序变得更加容易。
实现应用程序的数据访问层已经很麻烦了。为了执行简单的查询、分页和审计,必须编写太多的样板代码。Spring Data JPA的目标是通过减少实际需要的工作量来显著改进数据访问层的实现。作为一名开发人员,您需要编写存储库接口,包括自定义查找器方法,Spring将自动提供实现。
2.2 SpringData JPA的使用
SpringData JPA是一种ORM(Object Relational Mapping)框架,需要配合实体类(bean)和数据库表做关系映射,并配置好映射关系共同使用。
具体使用步骤:
① 书写实体类(bean);
② 编写Dao接口操作实体类数据库表;
③ 配置文件中,配置SpringData JPA;
④ 书写controller进行访问;
① 书写实体类(bean)
@Entity // 通知JPA此类是个实体类(和数据库映射的类)
@Table(name = "tbl_user")// 指明与那个数据库表映射,如果忽略则默认表名就是类名的缩写。数据库中可以没有此表,框架会自动创建
public class User {
@Id //表明此属性为主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 表明id自增
private Integer id;
@Column(name = "username", length = 50) // 指明此属性数据库表对应的列名
private String name;
@Column // 省略默认列名为属性名
private Integer sex;
@Column
private String email;
@Column
private Date birthday;
public User() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
", email='" + email + '\'' +
", birthday=" + birthday +
'}';
}
}
② 编写Dao接口操作实体类数据库表
public interface UserRepository extends JpaRepository<User,Integer> {
}
③ 配置文件中,配置SpringData JPA
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://139.224.83.90:3306/base_crud?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
# 使用DruidSource数据源
type: com.alibaba.druid.pool.DruidDataSource
# 数据源连接配置相关
# 初始化大小,最小,最大
initialSize: 5
minIdle: 5
maxActive: 20
# 配置获取连接等待超时时间
maxWait: 60000
# 配置检测间隔时间,检测会关闭空闲连接,单位时是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在连接池中最小存活时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 用来检测连接是否为有效SQL,必须为一个查询语句
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
# 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
testOnBorrow: false
# 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
testOnReturn: false
# 是否缓存preparedStatement,mysql5.5+建议开启
poolPreparedStatements: true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
# jpa相关的配置
jpa:
hibernate:
# 更新或创建数据表结构
ddl-auto: update
# 控制台显示SQL
show-sql: true
server:
port: 9090
servlet:
context-path: /jpa
④ 书写controller进行访问
@RestController
public class UserController {
@Autowired
UserRepository userRepository;
@GetMapping("/saveUser")
public User saveUser(User user) {
User saveUser = userRepository.save(user);
return saveUser;
}
@GetMapping("/deleteUserById/{id}")
public String deleteUserById(@PathVariable("id") Integer id) {
userRepository.deleteById(id);
return "删除成功";
}
@GetMapping("/updateUser")
public User updateUser(User user) {
User updateUser = userRepository.save(user);
return updateUser;
}
@GetMapping("/getUsers")
public List<User> getUsers() {
List<User> users = userRepository.findAll();
return users;
}
@GetMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id) {
User user = userRepository.getOne(id);
return user;
}
}
关于SpringData JPA的内容这里仅介绍了和SpringBoot整合的使用,后续会书写更多关于SpringBoot整合的博客。关于SpringData JPA的使用后续也会写博客详细说明的,敬请期待ヾ(•ω•`)o