Repository(包括子接口)位于Spring Data Common的lib里面,是Spring Data 里面做数据库操作的最底层的抽象接口,最顶级的父接口,源码中什么方法都没有,仅仅起到一个标示作用。
管理域类以及域类的id类型作为类型参数,此接口主要作为标记接口捕获要使用的类型,并帮助你发现扩展此接口的接口。Spring底层做动态代理的时候发现只要是它的子类或者实现类,都代表储存库操作。
Repository源码如下:
package org.springframework.data.repository; import org.springframework.stereotype.Indexed; @Indexed public interface Repository<T, ID> { }
有了这个类,我们就能够顺藤摸瓜,找到好多 Spring Data Jpa 提供的基本接口和操作类,及其实现方法。这个接口定义了所有 Repository 操作中的实体和ID两个泛型参数。我们不需要继承任何接口,只要继承这个接口,就可以使用Spring JPA里面提供的很多约定的方法查询和注解查询。
首先继承 Repository 的就是 CrudRepository 了,此类提供了公共的通用 CRUD 方法。
@NoRepositoryBean public interface CrudRepository<T, ID> extends Repository<T, ID> { <S extends T> S save(S var1); <S extends T> Iterable<S> saveAll(Iterable<S> var1); Optional<T> findById(ID var1); boolean existsById(ID var1); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> var1); long count(); void deleteById(ID var1); void delete(T var1); void deleteAll(Iterable<? extends T> var1); void deleteAll(); }
SimpleJpaRepository里面的实现方法
public <S extends T> S save(S entity) { if (entityInformation.isNew(entity) ) { em.persist(entity); return entity; } else { return em.merge(entity); }
我们发现它是先检查传进去的实体是不是存在,然后判断是新增还是更新;是不是存在两种根据机制,一种是根据主键来判断,另一种是根据Version来判断。如果我们去看JPA控制台打印出来的SQL,最少会有两条,一条是查询,一条是insert或者update。
PS 其他的方法:保存全部、查找、是否存在、删除等方法就不再赘述。
通过类的关系图,我们可以看到PagingAndSortingRepository继承CrudRepository所有的基本方法,它增加了分页和排序等对查询结果进行限制的基本的、常用的、通用的一些分页方法。
package org.springframework.data.repository; import java.io.Serializable; import org.springframework.data-domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @NoRepositoryBean public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable);
1、根据排序取所有对象的集合。
2、根据分页和排序进行查询,并用Page对象封装。Pageable对象包含分页和Sort对象。
PagingAndSortingRepository和CrudRepository都是Spring Data Common的标准接口,如果我们采用JPA,那它对应的实现类就是Spring Data JPA的model里面的SimpleJpaRepository。如果是其他NoSQL的实现Mongodb,那它的实现就在Spring Data Mongodb的model里面。
JpaRepository到这里可以进入分水岭了,上面的那些都是Spring Data为了兼容NoSQL而进行的一些抽象封装,从JpaRepository开始是对关系型数据库进行抽象封装。从类图可以看得出来它继承了PagingAndSortingRepository类,也就继承了其所有方法,并且实现类也是SimpleJpaRepository。从类图上还可以看出JpaRepository继承和拥有了QueryByExampleExecutor的相关方法。
@NoRepositoryBean public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { //无条件查询 获取整个表 相当于 SELECT * FROM table_name; List<T> findAll(); //增加排序 List<T> findAll(Sort sort); //通过一个id序列获取列表 List<T> findAllById(Iterable<ID> ids); //通过id查询 T getOne(ID id); ... }
通过源码和CrudRepository相比较,它支持Query By Example,批量删除,提高删除效率,手动刷新数据库的更改方法,并将默认实现的查询结果变成了List。
SimpleJpaRepository是JPA整个关联数据库的所有Repository的接口实现类。如果想进行扩展,可以继承此类,如QueryDsl的扩展,还有默认的处理机制。如果将此类里面的实现方法看透了,基本上JPA的API就能掌握大部分。同时也是Spring JPA动态代理的实现类,包括我们后面讲的Query Method。