spring data:核心概念与应用(1)

发布于:2024-08-20 ⋅ 阅读:(144) ⋅ 点赞:(0)


使用过 JPA 的同学比较了解在 Spring 体系的 web 服务开发中,有个比较方便的 dao 工具 repository,并伴随着 Entity 形成的一系列方法能大大加快开发进程,本系列就以 Spring Data 系列逐步讲解该体系的架构和源码实现。

核心概念

repository
Spring data 的中心接口。它需要 Domain 类以及Domain 类的标识符类型作为类型参数。必须有主键。CrudRepository和ListCrudRepository接口为所管理的实体类提供了复杂的CRUD功能。

public interface CrudRepository<T, ID> extends Repository<T, ID> {

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

  Optional<T> findById(ID primaryKey); 

  Iterable<T> findAll();               

  long count();                        

  void delete(T entity);               

  boolean existsById(ID primaryKey);   

  // … more functionality omitted.
}

PagingAndSortingRepository 和 ListPagingAndSortingRepository 提供分页功能。

public interface PagingAndSortingRepository<T, ID>  {

  Iterable<T> findAll(Sort sort);

  Page<T> findAll(Pageable pageable);
}

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));

定义Repository接口

定义 Repository 接口需要继承 Repository 并将泛型指定为 Domain 类和该类的主键。需要 crud 的继承 CrudRepository 或者它的派生类。

Repository 微调

接口的微调可以通过继承 CrudRepository ListCrudRepository 或者 @RepositoryDefinition 自己定义。如果想写个基类供继承,可以添加 @NoRepositoryBean 注解:

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {

  Optional<T> findById(ID id);

  <S extends T> S save(S entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
  User findByEmailAddress(EmailAddress emailAddress);
}

JPA 配置通过 EnableJpaRepositories 注解开启:

@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {

  @Bean
  EntityManagerFactory entityManagerFactory() {
    // …
  }
}

投影

投影是在进行性能优化非常重要的部分,一般的 sql 规范都会讲禁止使用 select * 来查询,而一般印象里 JPA 或者 hibernate相关的dao层技术里都会把select 将所有的字段进行平铺。这里的投影就给了我们选择查询字段的机会。

class Person {

  @Id UUID id;
  String firstname, lastname;
  Address address;

  static class Address {
    String zipCode, city, street;
  }
}

interface PersonRepository extends Repository<Person, UUID> {

  Collection<Person> findByLastname(String lastname);
}

投影选择:

interface NamesOnly {

  String getFirstname();
  String getLastname();
}
interface PersonRepository extends Repository<Person, UUID> {

  Collection<NamesOnly> findByLastname(String lastname);
}

动态投影:

interface PersonRepository extends Repository<Person, UUID> {
  <T> Collection<T> findByLastname(String lastname, Class<T> type);
}

void someMethod(PersonRepository people) {

  Collection<Person> aggregates =
    people.findByLastname("Matthews", Person.class);

  Collection<NamesOnly> aggregates =
    people.findByLastname("Matthews", NamesOnly.class);
}

网站公告

今日签到

点亮在社区的每一天
去签到