Repository位于Spring Data Common的org/springframework/data/repository中,它是Spring Data里做数据库操作的最底层的抽象接口、最顶层的父类。
Repository源码:
package org.springframework.data.repository;
import org.springframework.stereotype.Indexed;
@Indexed
public interface Repository<T, ID> {
}
源码中其实没有方法,只是一个标识作用。该接口主要作为标记接口捕获要使用的类型,并帮助你发现扩展此接口,Spring底层做动态代理的时候发现只要是它的子类或者实现类都代表存储库操作
1、通过IDEA工具,打开Repository.class,通过查看组织结构可以看到
2、通过打开类UserRepository.class,查看层次关系图。
3、通过打开QueryDslJpaRepository.class,查看层次关系图。
4、通过打开UserRepository.java,打开类结构图。
以上三种视图是开发过程中经常用到的视图。
提供了最基础的CRUD方法。包括根据ID查询,查询所有,根据ID删除等等。
CrudRepository源码:
package org.springframework.data.repository;
import java.util.Optional;
@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();
}
1、<S extends T> S save(S var1)
:保存实体方法。(方法来源SimpleJpaRepository.class)
@Transactional
public <S extends T> S save(S entity) {
if (this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
可以从上面代码中看到:首先检查传递进行的实体是否存在,然后判断是否为新增还是更新,检查的机制是通过主键判断,另一种方式是通过Version来判断。如果我们去JPA控制台打印输出sql,最少会由两条,一条是查询,一条是insert或update方法。
2、批量保存。实现方法同保存实体方法大同小异,实现方式就是for循环调用上面的save方法
3、根据主键查询实体
4、根据主键判断实体是否存在
5、查询实体的所有列表
6、根据主键列表查询实体列表
7、查询总数
8、void deleteAll()
根据主键删除。(方法来源SimpleJpaRepository.class)
@Transactional
public void deleteById(ID id) {
Assert.notNull(id, "The given id must not be null!");
this.delete(this.findById(id).orElseThrow(() -> {
return new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", this.entityInformation.getJavaType(), id), 1);
}));
}
实现原理:先去查询一下,再做保存,不存在抛出异常。
只需要自己的Repository继承CrudRepository即可。
例如,在我们有一个UserRepository继承CrudRepository
import org.springframework.data.repository.CrudRepository;
/**
* TODO
*
* @author: Yizq
* @data: 2020/8/23 4:40 下午
*/
public interface UserRepository extends CrudRepository<User,Long> {
}
它在CurdRepository的基础上增加了分页和排序等对查询结果进行限制的基本方法。
PageingAndSortingRepository源码:
package org.springframework.data.repository;
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 CrudRepository<T, ID> {
// 根据排序取所有对象的集合
Iterable<T> findAll(Sort var1);
// 根据分页和排序进行查询,并且Page对象封装。Pageable对象中包含分页和sort对象。
Page<T> findAll(Pageable var1);
}
只需要继承PageingAndSortingRepository的接口即可,其他不需要做任何修改
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* TODO
*
* @author: Yizq
* @data: 2020/8/23 4:40 下午
*/
public interface UserRepository extends PagingAndSortingRepository<User,Long> {
}
UserController修改操作如下:
/**
* TODO
*
* @author: Yizq
* @data: 2020/8/23 4:44 下午
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/page")
@ResponseBody
public Page<User> getAllUserByPage() {
return userRepository.findAll(PageRequest.of(1,
20,
Sort.by(Sort.Direction.ASC, "name")
));
}
}
ps:在版本
Springboot2.2.1+
中不再支持new PageRequest和new Sort来创建分页和排序对象,需要更改为以上操作
JpaRepository到这里进入分水岭,以上的接口都是Spring Data为了兼容NoSQL而进行抽象封装,从JpaRepository开始对关系型数据进行抽象封装。
JpaRepository源码:
ackage org.springframework.data.jpa.repository;
import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
通过源码和CrudJRepository相比较,它支持Query By Example,批量删除,提高删除效率,手动刷新数据库的更该方法,并将默认实现的查询结果变成了List。
只需要将自己的Repository继承JpaRepository即可,比如
import org.springframework.data.jpa.repository.JpaRepository;
/**
* TODO
*
* @author: Yizq
* @data: 2020/8/23 4:40 下午
*/
public interface UserRepository extends JpaRepository<User,Long> {
}
SimpleJpaRepository是JPA整个关联数据库的所有Repository的接口实现类。如果想扩展,可以继承此类,还有默认的处理机制。
原文:https://www.cnblogs.com/xianbeier/p/13688409.html