Spring Data JPA
1. 什么是Spring Data?
Spring 的一个子项目。用于简化数据库访问,支持NoSQL和关系数据库存储。其主要目标是使数据库的访问变得方便快捷。
1.1 Spring Data 项目所支持NoSQL存储:
- - MongoDB(文档数据库)
- - Neo4j (图形数据库)
- - Redis(键/值存储)
- - Hbase(列族数据库)
1.2 Spring Data 项目所支持的关系数据存储技术:
- - JDBC
- - JPA
2. 什么是Spring Data JPA ?
JPA Spring Data: 致力于减少数据访问层(DAO)的开发量。开发者唯一要做的,就只是声明持久层的接口,其他都交给Spring Data JPA 来帮你完成!
Spring Data JPA 是spring data 项目下的一个模块。 提供了一套基于JPA标准操作数据库的简化方案。底层默认的是依赖 Hibernate JPA来实现的。
2.1 Spring Data JPA的技术特点:
我们只需要定义接口并集成 Spring Data JPA中所提供的接口就可以了。不需要编写接口实现类。
2.2 Spring Data JPA接口继承结构
SpringDataJPA底层原理
使用JDK自带的动态代理机制:
接口:JpaRepository,JpaSpecificationExecutor
目标类:SimpleJpaRepository
代理类:usrsDao接口的实现类
2.2.1 Spring Data JPA接口概述
①、Repository :仅仅是一个标识,表名任何继承它的均为仓库接口类
②、CurdRepository : 继承Repository ,实现了一组CURD相关的方法
③、PagingAndSortingRepository :继承CurdRepository ,实现了一组分页排序相关的方法
④、JpaRepository : 继承PagingAndSortingRepository ,实现一组Jpa 规范相关的方法,。 其特点是可以帮助我们将其他接口的方法的返回值做适配处理。可以使得我们在开发时更方便的使用这些方法。
⑤、自定义 的 XXXRepository :需要继承JpaRepository ,这样的XxxRepository 接口就具备了通用的数据访问控制层的能力。
⑥、JpaSpecificationExecutor :不属于Repository 体系,实现一组JpaCriteria 查询相关的方法,完成多条件查询,并且支持分页与排序
3.Spring整合Spring Data JPA
3.1 步骤:
3.1.1 创建项目
3.1.2 导入jar包
spring-ioc :
spring-aop:
spring-jdbc
spring-orm
spirng-test
apatch-logging
spring-data-jpa
log4j:
3.1.3 在类路径下创建applicationContext.xml
配置了
3.1.4 在类路径下创建jdbc.properties属性文件
3.1.5 创建实体类
3.1.6 继承Repository 接口实现简单的查询,更新
若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repository Bean 纳入到IOC容器中,进而可以在该接口中定义满足一定规范的方法
实际上,也可以通过@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class) 注解来代替 extends Repository
Repository 接口是 Spring Data JPA中为我我们提供的所有接口中的顶层接口
Repository 提供了两种查询方式的支持
3.1.6.1基于方法名称命名规则查询
简单查询条件 :查询某一个实体类或是集合
在Repository 子接口中声明方法:
①、不是随便声明的,而需要符合一定的规范
②、查询方法以 find | read | get 开头
③、涉及条件查询时,条件的属性用条件关键字连接
④、要注意的是:条件属性以首字母大写
⑤、支持属性的级联查询。若当前类有符合条件的属性,则优先使用,而不使用级联属性。若需要使用级联属性,则属性之间使用_连接
spring data 支持的关键字
示例:
接口
测试
3.1.6.2 基于@Query 注解查询
基于@Query 注解查询有两种语句查询方式:
1)通过JPQL语句查询:他和 HQL 语法及其相似。
2)通过SQL语句查询
示例:
接口:
测试:
3.1.7 继承CrudRepository接口实现简单的CRUD
注意:CrudRepository中的更新方法与保存方法一致,此时需要给定主键(原理:先根据主键查询到对象,再根据给定的其他属性更新)
接口:
测试
3.1.8 继承PagingAndSortingRepository接口实现简单的分页和排序的处理
接口
测试:
3.1.9 继承JpaSpecificationExecutor接口实现复杂多条件的CRUD,并做分页和排序处理
接口:
是因为只有继承了repository接口spring-data-jpa才会创建接口的实现代理类。
测试:
3.1.10 用户自定义 Repository接口
3.1.10.1 创建自定义接口
3.1.10.2 创建自定义接口实现类
3.1.10.3 代理接口继承自定义接口
3.1.10.4 测试
3.1.11 关联映射操作
3.1.11.1 一对一的关联关系
需求:用户与角色的一对一的关联关系
用户:一方
角色:一方
3.1.11.1.1 创建接口:
3.1.11.1.2 创建关联的实体类:
用户类:
角色类:
3.1.11.1.3 测试
3.1.11.2 一对多的关联关系
需求:从角色到用户的一对多的关联关系
角色:一方
用户:多方
3.1.11.2 .1 修改实体类
用户类:
角色类:
注意:一对多,一方必须做懒加载处理,即在注解后加上:fetch = FetchType.EAGER
3.1.11.2 测试
3.1.11.3 多对多的关联关系
需求:一个角色可以拥有多个菜单,一个菜单可以分配多个角色。多对多的关联关系
角色:多方
菜单:多方
3.1.11.3.1 创建实体类
角色类:
菜单类:
3.1.11.3.2 测试
遇到的异常:
异常1:
failed to lazily initialize a collection of role 异常
原因:在实体类里,对应有一对多的外键关系,每一个一对多的关系查询的时候都涉及到一个懒加载,所以说,每一个OneToMany上都要添加fetch=FetchType.EAGER
解决方法:在注解manytomany后加fetch=FetchType.EAGER,如下图所示:
异常2:
Noproperty toPredicate found for type User!报错
解决:
是因为dao层多写了Specification
将Specification