Spring Data JPA渐进式学习-Repostory

源码

这就是Repostory的源码,里边没有任何方法。

package org.springframework.data.repository; import org.springframework.stereotype.Indexed;

@Indexed public interface Repository<T, ID> {
}

但是只要继承了这个类,就可以实现JPA的一些默认实现方法。

Repostory类层次关系


从层级关系可以看出来分了四大类,下边简单介绍一下。

ReactiveCrudRepository

这个是响应式编程的一个类,主要支持NoSQL方面的操作。目前主要支持了Cassandra,MongoDB,Redis的实现。

RxJava2CrudRepository

这个是为了支持RxJava2做的标准响应式编程的接口。

CoroutineCrudRepository

这个是为了支持Kotlin语法而增加的

CrudRepository

这个则是我学习的重点

我们再看一下Repository的类层级关系图:我把类的作用标注了一下。


Repostory接口

这个接口没有默认方法,也就是说,我们增加了什么方法,就可以使用什么方法。

public interface UserRepository extends Repository<UserInfo,Integer> { List<UserInfo> findByName(String name); List<UserInfo> findByAgeAndName(Integer age, String name);
}

当我们添加了两个方法如上代码所示,一个根据name找user,一个根据age和name找用户。

这时,之前写的save和findAll方法就报错了,因为这里边没有这两个方法。



UserRepository实例通过继承Repository,使Spring容器知道UserRepository是操作数据库的类,并可以对数据库进行CRUD操作。

CrudRepository接口

我们将每个方法的作用用注解进行标注,以便更直观的查看。

@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(); //根据主键的list列表查询所有实体 Iterable<T> findAllById(Iterable<ID> var1); //查询总数 long count(); //根据主键删除 void deleteById(ID var1); //根据实体类对象删除 void delete(T var1); //根据主键的List删除所有 void deleteAll(Iterable<? extends T> var1); //根据主键删除 void deleteAll();
}

以上这些方法就是CrudRepository对外暴露的最常见的接口,当我们的UserRepository继承CrudRepository之后,我们就可以使用这些方法操作我们的UserInfo表了。


这里我们特别看一些save和delete方法

<S extends T> S save(S var1);

从源码可以看出,会先判断是否是新的数据,若是新的则新增,若是已有的则修改已有数据。

@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);
    }
}

<S extends T> Iterable<S> saveAll(Iterable<S> var1);

这里可以看出,尽管是saveAll()但也是轮询然后一个一个调save方法保存的,并没有性能上的提升。

@Transactional public <S extends T> List<S> saveAll(Iterable<S> entities) {
    Assert.notNull(entities, "Entities must not be null!");
    List<S> result = new ArrayList();
    Iterator var3 = entities.iterator(); while(var3.hasNext()) {
        S entity = var3.next();
        result.add(this.save(entity));
    } return result;
}

void deleteById(ID var1);

delete方法则是先判断了传入的实体是否存在,若是不存在还抛出了错误。

@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);
    }));
}

PagingAndSortingRepository接口

这个接口继承自CrudRepository,然后添加了主要用于分页查询排序查询的两个方法。

源码如下:

@NoRepositoryBean public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { //排序查询 Iterable<T> findAll(Sort var1); //分页查询 Page<T> findAll(Pageable var1);
}

这个接口只有两个方法,分别当排序分页的时候使用。

使用的时候,直接让我们的UserRepository继承PagingAndSortingRepository即可。

public interface UserRepository extends PagingAndSortingRepository<UserInfo,Integer> {

}

这时查询的时候,就可以使用分页和排序了

分页

这段代码的意思是,取第一页,每页20个数据,根据name排序

@GetMapping(path = "users") @ResponseBody @WebLog(printResult = true) public Page<UserInfo> getAllUsers(){ return userRepository.findAll(PageRequest.of(1,20, Sort.by(new Sort.Order(Sort.Direction.ASC,"name"))));
}

排序

这则是根据name字段逆序排序

@GetMapping(path = "users") @ResponseBody @WebLog(printResult = true) public Iterable<UserInfo> getAllUsers(){ return userRepository.findAll(Sort.by(new Sort.Order(Sort.Direction.DESC,"name")));
}
#Java##Spring##程序员#
全部评论

相关推荐

kzn_ye:看成被正职干了半年,我还以为。。。
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务