1. SpringData概述
1.1 持久层开发的问题
随着互联网技术的发展,现在的企业开发中用到的用于数据存储的产品,不再仅仅是关系型数据库,而是要根据场景需要选择不同的存储技术,比如用于缓存热点数据的redis,用于存储文档数据的mongodb,用于支持强大搜索功能的elasticsearch等等。
在Java中,对于上面所说的产品都提供了优秀的访问技术。比如针对关系型数据库的mybatis、jpa等技术,针对于redis的jedis技术等等….. 这些技术虽然可以很好的针对各个存储产品进行访问操作,但同时也带来了新的问题,那就是不同的持久层技术的API是不一样的。
这样一来,开发人员就必须同时掌握多种数据访问技术,这无疑增加了开发成本。那么我们会想,有没有这样一种技术,它可以使用一套API支持各个不同的存储的访问呢?就在这样的需求下,SpringData产生了。
1.2 SpringData 简介
1.2.1 什么是SpringData
SpringData是一个用来简化dao层开发的框架。它在保证了各个底层存储特性的同时,提供了一套统一的数据访问API。它可以很好的支持常用的关系型数据库和非关系型数据库。
使用SpringData作为dao层开发技术,将大大简化代码量,而且其API比各个技术的原生API更加简单易用。
1.2.2 SpringData的主要模块
SpringData支持的持久层技术非常多,我们只介绍几个常见的:
- Spring Data common SpringData 的核心模块,定义了SpringData的核心功能
- Spring Data JDBC 对JDBC的Spring Data存储库支持
- Spring Data JPA 对JPA的Spring Data存储库支持
- Spring Data MongoDB 对MongoDB的基于Spring对象文档的存储库支持
- Spring Data Redis 封装Jedis技术,对redis实现访问操作
- Spring Data Elasticsearch 对Elasticsearch实现访问操作
2. JPA回顾
2.1 JPA 基础
Hibernate 是一个全自动的ORM框架,是对 JDBC技术的封装。它在实体类和数据库表之间建立了映射关系,使得程序员可以使用面向对象编程思维来操纵数据库,而Hibernate会自动给我们生成 SQL语句。
JPA 的全称是 Java Persistence API,即 Java 持久化 API,是 SUN 公司推出的一套基于 ORM 的规范,注意不是 ORM 框架——因为 JPA 并未提供 ORM 实现,它只是提供了一些编程的 API 接口。
2.2 JPA 实战
2.2.1 目标
搭建Jpa环境,并实现一条数据的增删改查。
2.2.2 准备数据库环境
1 | --准备数据库,创建一张文章表备用 |
2.2.3 创建 java工程,导入坐标
1 | <dependencies> |
2.2.4 创建实体类
1 | public class Article implements Serializable { |
2.2.5 在实体类中配置映射关系
1 | /** |
2.2.6 加入 JPA 的核心配置文件
在maven工程的resources路径下创建一个名为META-INF的文件夹,在文件夹下创建一个名为persistence.xml的配置文件。注意: META-INF文件夹名称不能修改,persistence.xml文件名称不能改。
1 |
|
2.2.7 测试
2.2.7.1 实现保存操作
1 | /** |
2.2.7.2 实现查询操作
1 | /** |
2.2.7.3 实现修改操作
1 | /** |
2.2.7.4 实现删除操作
1 | /** |
2.3 JPA 的重要API介绍
2.3.1 EntityManagerFactory
EntityManagerFactory接口主要用来创建EntityManager实例
EntityManagerFactory是一个线程安全的对象,并且其创建极其浪费资源,所以编程的时候要保持它是单例的。
2.3.2 EntityManager
在JPA规范中,EntityManager是操作数据库的重要API,他是线程不安全的,需要保持线程独有。
重要方法说明:
- getTransaction: 获取事务对象
- persist:保存操作
- merge:更新操作
- remove:删除操作
- find/getReference:根据id查询
3. SpringData JPA基础
3.1 SpringData JPA 简介
SpringData JPA是Spring Data家族的一个成员,是Spring Data对JPA封装之后的产物,目的在于简化基于JPA的数据访问技术。使用SpringData JPA技术之后,开发者只需要声明Dao层的接口,不必再写实现类或其它代码,剩下的一切交给SpringData JPA来搞定 。
3.2 SpringData JPA 快速入门
3.2.1 目标
搭建SpringData JPA环境,并实现一条数据的增删改查。
3.2.2 准备数据环境
下面的操作让JPA自动生成表结构
3.2.3 创建 java工程,导入坐标
1 | <dependencies> |
3.2.4 创建实体类
1 | public class Article implements Serializable { |
3.2.5 在实体类中配置映射关系
1 | /** |
3.2.6 编写 dao接口
使用 Spring Data JPA操作数据库,只需要按照框架的规范提供 dao 接口,不需要提供在接口中定义方法,也不需要为接口提供实现类就能完成基本的数据库的增删改查等功能。
在 Spring Data JPA 中,对于定义符合规范的 Dao 层接口,我们只需要遵循以下几点就可以了:
- 创建一个 Dao 层接口,并实现 JpaRepository 和 JpaSpecificationExecutor
- 提供相应的泛型
1 | /** |
3.2.7 添加 Spring整合Jpa的配置文件
1 |
|
3.2.8 测试
1 | /** |
3.3 SpringData Jpa 运行原理分析
3.3.1 SpringData中的几个重要接口
思考一个问题:自定义的接口中没有写任何的方法声明,那么测试类中调用的接口中的方法是哪来的呢?
1 | 自定义的接口继承了两个接口,方法肯定来自里面,追踪关系得到下面的继承关系 |
3.3.2 SpringData Jpa 底层运行原理
思考一个问题:我们找到了定义方法的接口,但并没有看到实现类,没有实现来就无法创建对象,那么真正干活的实现类到底在哪,它又是如何产生对象的呢?
下面我们通过debug的形式,寻找答案:
1、在运行时,Spring会使用JdkDynamicAopProxy为dao接口生成一个代理对象
2、那么这个代理对象是根据那个类代理出来的呢?点击进入JdkDynamicAopProxy源码查看invoke方法,发现targetSource代理的是SimpleJpaRepository类
3、通过对SimpleJpaRepository中代码的分析,我们看到最终执行保存的是EntityManager对象
总结:使用 SpringData JPA开发底层还是用的JPA的API,SpringData JPA只是对标准 JPA 操作进行了进一步封装,已达到简化了Dao层代码开发的目的。
3.3.3 SpringData Jpa 与 Jpa 及 Hibernate的关系
3.3.4 SpringData Jpa CUD方法
1 | /** |
4. SpringData JPA的多种查询方式
4.1 父接口方法查询
我们自定义的Dao接口可以使用它的父接口提供的方法,可以使用的方法如下图所示。
1 | /** |
4.2 方法命名规则查询
顾名思义,方法命名规则查询就是根据方法的名字,就能创建查询。只需要按照SpringData JPA提供的方法命名规则定义方法的名称,就可以完成查询工作。
SpringData JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询.
按照SpringData JPA定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。
1 | /** |
1 | /** |
关键字 | 例子 | 对应的JPQL语句 |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ? 2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | indByFirstnameIs, 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 ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection 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) = U |
4.3 JPQL 查询
使用SpringData JPA提供的查询方法已经可以解决大部分的应用场景,但是对于某些业务来说,我们还需要灵活的构造查询条件,这时就可以使用@Query注解,结合JPQL的语句方式完成查询。
JPQL,全称是Java Persistence Query Language。JPQL语句是JPA中定义的一种查询语言,此种语言的用意是让开发者忽略数据库表和表中的字段,而关注实体类及实体类中的属性。
它的写法十分类似于SQL语句的写法,但是要把查询的表名换成实体类名称,把表中的字段名换成实体类的属性名称。
1 | /** |
1 | /** |
4.4 本地 SQL查询
1 | /** |
4.5 Specifications 动态查询
有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在 Spring Data JPA 中可以通过 JpaSpecificationExecutor 接口查询。相比 JPQL,其优势是类型安全,更加的面向对象,缺点是书写比较麻烦。
1 | /** |
5. SpringData JPA实现多表操作
5.1 多表关系分析
数据库中多表之间存在着三种关系,如图所示。
1 | 从图可以看出,系统设计的三种实体关系分别为: 多对多、一对多和一对一关系。 |
5.2 案例表间关系
5.3 一对一关系
5.3.1 数据环境
article和article_data的一对一关系
5.3.2 创建实体类,并配置表间关系
5.3.2.1 创建文章类
1 | /** |
5.3.2.2 创建文章详情类
1 | /** |
5.3.3 添加 ArticleDao接口
1 | /** |
5.3.4 测试
1 | /** |
5.4 一对多关系
5.4.1 数据环境
article和comment的一对多关系
5.4.2 创建实体类,并配置表间关系
5.4.2.1 修改文章类,添加文章跟评论的映射
1 | /** |
5.4.2.2 创建文章评论类
1 | /** |
5.4.3 添加 CommentDao接口
1 | /** |
5.4.4 测试
1 | /** |
5.5 多对多关系
5.5.1 数据环境
article跟type之间的多对多关系
5.5.2 创建实体类,并配置表间关系
5.5.2.1 修改文章类,添加文章跟评论用户的多对多关系
1 | /** |
5.5.2.2 创建文章用户类
1 | /** |
5.5.3 添加 TypeDao接口
1 | /** |
5.5.4 测试
1 | /** |
-------------本文结束感谢您的阅读-------------
本文标题: SpringData(一)
本文链接: https://wgy1993.gitee.io/archives/a2f2c444.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
