数据库访问中间件
什么是ORM框架
对象关系映射(Obiect Relational Mapping,简称ORM),用于实现面向对象编程语言里不同类型系统的数据之间的转换。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射;
- 异构性:ORM可以解决数据库与程序间的异构性,比如在Java中我们使用String表示字符串,而Oracle中可使用varchar2,MySQL中可使用varchar,SQLServer可使用nvarchar。
- 映射:ORM提供了实现持久化层的另一种模式,采用映射元数据(XML)来描述对象-关系的映射细节,使得ORM中间件能在任何一个Java应用的业务逻辑层和数据库之间充当桥梁。
有哪些经典的ORM框架
- Hibernate:全自动的框架,强大、复杂、笨重、学习成本较高
- MyBatis:半自动的框架,必须要自己写sql
- JPA:全称Java Persistence API,是Java自带的框架
Mybatis
Mybatis的介绍
- MyBatis是一款优秀的持久层框架(它前身是apache的一个开源项目iBatis),支持定制化SQL、存储过程以及高级映射。
- MyBatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
Mybatis的架构
接口层:接口层主要定义的是与数据库进行交互的方式。
- 接口层中,调用CRUD的方式有两种:一、基于Mybatis自带的Statement ID;二、基于Mapper接口。
数据处理层:这是Mybatis的核心,负责参数映射和动态SQL生成,生成之后Mybatis执行SQL语句,并将返回的结果映射成自定义的类型。数据处理层主要负责: 参数映射(ParameterHandler)——>SQL解析(SqlSource)——>SQL执行(Executor)——>结果处理和映射(ResultSetHandler)
框架支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
引导层:基于XML配置方式和基于Java API方式。
Mybatis的主要工作流程
Mybatis中的主要成员以及结构
配置方面——Configuration:Mybatis的所有的配置信息都保存在这里面,分成全局配置文件以及映射的配置文件,而映射的配置文件当中又存储了相关的SQL操作。所以在MappedStatement里面,封装了mapper配置文件里面的相关的SQL操作,通过SqlSource来生成动态SQL语句,并且把他封装到BoundSql里面。而ResultMap就是Map里面定义的自定义结果集。
结构层次:
- SqlSession:作为MyBatis工作的最顶层的API接口,作为会话访问,完成增删改查功能。
- Executor:MyBatis执行器,是MyBatis调度的核心,负责动态语句的生成和查询缓存的维护。
- StatementHandler:封装了JDBC的所有Statement操作,负责处理JDBC的Statement的交互,包括对Statement设置参数,以及将JDBC返回的resultSet结果集转换成List。
- ParameterHandler:负责根据传递的参数值,对Statement对象设置参数。
- ResultSetHandler:负责将resultSet集合转换为List。
- TypeHandler<T>:负责JDBCType与JavaType之间的数据转换;
- 负责对Statement对象设置特定的参数;
- 对Statement返回的结果集resultSet,取出特定的列。
Springboot整合Mybatis的流程
Springboot整合Mybatis的相关配置
mysql的配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&
useUnicode=true&characterEncoding=utf-8&useSSL=true
#用户名、密码由自己设置
spring.datasource.username=root
spring.datasource.password=root
#在 Spring Boot 2.1.0 中,com.mysql.jdbc.Driver已经过期,推荐使用 com.mysql.cj.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Mybatis的配置:
#设置mybatis的配置文件路径,默认是在resources的目录
mybatis.config-location=classpath:mybatis/mybatis-config.xml
#设置mybatis下面的mapper映射文件路径,默认是在resources的目录
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
#设置项目中实体类包路径;com.study.springboot_mybatis01.entity根据项目而定
mybatis.type-aliases-package=com.study.springboot_mybatis01.entity
#展示sql语句,com.study.springboot_mybatis01.repository.UsersDao根据项目而定
logging.level.com.study.springboot_mybatis01.repository.UsersDao=debug
Spring Data JPA的介绍以及入门
SpringData是什么
Spring Data是为了简化构建基于Sprng框架应用的数据访问技术,包括对关系数据库、非关系数据库、Map-Reduce框架、云数据服务等访问支持。它为我们提供使用统一的API标准来对数据访问层进行操作,这套标准包含了CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。
Spring Data的特点
-
支持对象关系映射
- 具备ORM框架的对象关系映射功能。
-
统一的Repository接口
-
Repository<T,ID extends Serializable>:统一接口
-
CrudRepository<T,ID extends Serializable>:基本的CRUD操作
-
PagingAndSortingRepository<T,ID extends Serializable>:基本CRUD及分页
-
-
统一的数据访问模板类 xxxTemplate
- 为非关系型数据库提供,如:MongoTemplate、RedisTemplate等
JPA的介绍
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。主要为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是一套规范,不是一套产品,比如Hibernate、TopLink、JDO是一套产品,如果这些产品实现了JPA规范,那么就可以称之为JPA的实现产品。
JPA的配置信息:
# 支持SQL输出
spring.jpa.show-sql=true
# format 一下 SQL 进行输出
spring.jpa.properties.hibernate.format_sql=true
# 自动生成开启,让表数据会自动跟随entity类的变化而变化
spring.jpa.properties.hibernate.hbm2ddl.auto = update
# 开启自动更新,若数据库没有对应的表,则生成;若有,则检查是否需要更改
spring.jpa.hibernate.ddl-auto = update
Spring Data与JPA的关系
Spring Data JPA的工作原理
JPA单表SQL操作-使用关键字拼凑方法
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstnameIs ,findByFirstnameEquals | … where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended % ) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended % ) |
Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in % ) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> age) | … where x.age not in ?1 |
True | findByActiveTrue() | … where x.active = true |
False | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
注意事项:
- 实体类属性名不要出现isXxx、getXxx的名称,会导致关键字拼凑出错。
- 实体类属性名中间只要出现了大写字母,就会导致数据库的字段名有下划线隔开,比如你是用isMarried属性名,那么实体类的字段名就会变成**
is_married
**,这样容易导致找不到值。 - 属性名类型是boolean类型的在某些数据库中会变成**bit(1)**类型,其中0为false,1为true。
无法解决的问题:
- 实体类的属性名与表的字段名无法映射,导致关键字找不到。
- CRUD操作方式比较另类。
- 涉及到多表操作。
单表SQL操作-使用注解手写sql语句
- 使用SQL语句来书写SQL。
- 使用HQL语句来书写SQL。
注意事项:
- 如果是删改操作,需要加
@Modifying
(你对表进行了删改操作)和@Transactional
(他会支持事务的操作) - 如果是SQL语句,请在
@Query
注解上加上NativeQuery = true
的属性,如果不加,就会默认为HQL语句 - 传参的方式有两种:
- 使用 ? + 数字的方式,数字从1开始,代表第几个参数;
- 使用 : + 参数名的方式,这种方式最好配合
@Param
注解一起使用。
Spring Data JPA的逆向工程操作和多表操作
- 使用数据接口:构建一个数据接口,里面的抽象方法就是SQL语句的查询结果的字段对应的
getXXX
的抽象方法。 - 使用集合:直接使用List/Map等集合嵌套的方式来获取到接收数据。
- 使用VO(View Object):单独构建一个跟页面展示数据对应的VO的实体类来接收数据。
注意事项:
- 使用数据接口的方式来接受查询的字段时要注意,必须要为要查询的字段名气别名,否则会无法取到。
多表复杂查询的一种方式——QueryDSL
什么是QueryDSL:
QueryDSL仅仅是一个通用的查询框架,专注于通过JavaAPI构建类型安全的Sql查询,也可以说QueryDSL是基于各种ORM框架以及Sql之上的一个通用查询框架,QueryDSL的查询,类似于SQL查询,只不过一个使用SQL一个使用代码来代替SQL。
注意:单表乃至简单的多表操作,都不推荐使用QueryDSL,使用JPA自带API简洁又效率,但是设计太复杂的查询,还是推荐使用QueryDSL。
官方学习文档:http://www.querydsl.com/static/querydsl/latest/reference/html/
总结
Springboot中的分页
Pageable分页
Pageable分页是Spring Data JPA默认提供的分页功能,直接继承JpaRepository就获得了该分页功能;
- JPA自带的分页方式,不需要添加额外的支持及配置;
- 页数是从0开始,到size-1为止;
- 单表、简单的多表操作分页排序使用它方便快捷。
PageHelper分页(Mybatis分页插件)
- 第三方插件,需要添加对应的依赖以及进行相关配置;
- 页数是从1开始,到size为止;
- 最佳搭档是Mybatis(由于PageHelpers是根据离他最近的一个sql执行,而jpa刚好是自动生成sql,所以PageHelper最好用mybatis。如果必须用jpa的话需要引入entitymanager+Query查询)
- 复杂的查询使用PageHelper可以让你更方便。
参考网址:
- GitHub地址:http://github.com/pagehelper/Mybatis-PageHelper
- 配置说明:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
- API文档:http://apdioc.gitee.com/free/Mybatis_PageHelper
配置:
#pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql