一、Spring Data介绍
- Spring Data是一款数据持久层框架, 能用于MySQL,Oracle,MongoDB,ElasticSearch,Redis,Neo4j等不同的数据库
- Spring Data减少了学习和开发成本,统一了数据访问层(DAO),实现对不同的底层存储数据库的采用相同的语法来访问
- Spring Data提供了通用Repository接口、通用模板、对象/数据存储映射(通过注解)
二、JPA
2.1 JPA介绍
- JPA和JDBC都是一组规范接口,都由SUN公司提出
- JDBC使用SQL语句操作数据库,JPA使用ORM框架把对象映射到SQL来操作数据库,JPA是在JDBC之上构建的
- JDBC移植性差,写的SQL语句是特定于底层具体数据库的,JPA则是通用的
- SpringBoot默认采用的JPA实现是Hibernate
2.2 Hibernate注解介绍
@Entity // 实体类
@Table(name="") // 表名
@Id // 主键
@Column // 属性和字段映射关系
@GeneratedValue(strategy="") // 主键生成策略
2.3 JPA对象状态(了解)
Spring Data JPA定义了几种不同的对象状态。在同一个事务里面对这些不同状态的数据进行更新、删除操作,可能会导致不同的结果。
- 临时状态(new):刚创建出来,不处于EntityManager中
- 持久状态:已经被EntityManager持久化到数据库
- 删除状态(removed)
- 游离状态(detached):数据库存在对应的数据,但是不处于EntityManager管控中
三、Spring Data JPA
3.1 Repository接口
为了减少样板代码,通过继承Repository实现基本的CRUD操作
- CrudRepository<T, ID>:实现基本的CRUD
- save/saveAll
- findById/existById/findAllById
- count
- deleteById/delete/deleteAllById/deleteAll
- PagingAndSortingRepository: 实现分页排序
- 分页请求对象 PageRequest
- 分页响应对象 Page
- 排序对象 Sort、TypedSort(方法引用方式,类型安全)
3.2 自定义操作
当Spring Data JPA Repository无法实现我们的需求,需要通过下面的方式自定义查询更新操作
3.2.1 JPQL
- JPQL可以使用对象名作为from的条件(nativeQuery=true,使用原始的sql进行查询,只能使用表名,不能用对象名)
- @Query:定义查询条件,可以省略select语句(若查询全部)
- 查询单条记录,返回值为单个实体,查询多条记录,返回List
- 两种传入参数的方式
- ?1 位置参数
- :paramName 具名参数
- 使用具名参数,方法参数接收需要结合@Param
- 增删改的操作,必须加上事务和@Modifying
- 增删改操作,返回修改的行数
- 对于插入方法,hibernate的JPA实现下,只支持insert...select方式
@Query("FROM Customer where custName=?1")
List<Customer> list = findByCustName(String custName);
3.2.2 约定的方法名
根据Spring Data JPA要约定的方法格式,只要按照这个格式命名,就能实现对应的查询。 通过IDEA JPA Buddy可以对这种方法有自动补全提示
3.2.2.1 主题关键字(方法前缀,决定当前方法的作用)
- find...By、read...By、get...By、query...By、search...By、stream...By
- exist...By
- count...By
- delete...By、remove...By
- ...First<n>...、...Top<n>... (放在find...By之间,前n条数据)
- ...Distinct... (放在find...By之间,去重)
3.2.2.2 谓词关键字(By后面的后缀,查询条件)
| 关键字 |
|---|
| Distinct |
| And |
| Or |
| Is,Equals |
| Between |
| IsNull,Null,IsNotNull,NotNull |
| Like,NotLike,StartingWith,EndingWith,Containing(需要手动传入%) |
| OrderBy |
| Not |
| In,NotIn |
| True,False |
| IgnoreCase |
3.2.3 Query by Example(不推荐)
动态条件查询,只支持字符串类型的查询,不支持嵌套或分组
3.2.3.1 使用
- 继承QueryByExampleExecutor<T>,findAll等方法里面就多了Example参数的方法
- Example对象:封装查询条件
- ExampleMatcher:条件匹配器,设置条件的行为
ExampleMathcer matcher = ExampleMathcer.matching()
.withIgnorePaths(xxx) // 忽略参数
.withIgnoreCase(xxx); // 忽略大小写
Example example = Example.of(po, matcher); // 根据po,matcher封装查询条件
findAll(example); // 查询
3.2.4 Specifications(不推荐)
动态条件查询
3.2.4.1 使用
- 继承JpaSpecificationExecutor<T>,findAll等方法里面就多了Specification参数的方法
3.2.5 Query DSL
- 继承QuerydslPredicateExecutor