Spring Boot 2.x实战63 - Spring Data 7 - Spring Data JPA查询(定制查询返回Projection:接口或对象)

2.6.1.8 Projection

Spring Data JPA的查询方法一般返回的是聚合根的一个多或多个实例。我们可以使用Projection,通过聚合根的属性来定制查询返回。

我们可以使用接口来定制返回值

public interface PersonProjectionInterface {

    String getName(); //1

    Address getAddress(); //2

    @Value("#{target.name + ' s age is' + target.age}") //3
    String getAgeDesc();

    default String getCityDesc(){ //4
        return getName() + " lives in " + getAddress().getCity();
    }

    @Value("#{@personProjectionHelper.getInfo(target)}") //5
    String getInfo();

    @Value("#{args[0] + ' ' + target.name + ' !'}") //6
    String getHello(String greeting);
}
  1. 可以直接设置聚合根的属性在返回里;

  2. 设置聚合根的属性对象在返回里;

  3. 可以使用@Value注解计算新的值,target代表聚合根的值;

  4. 可以使用default方法来定义运算逻辑;

  5. 可调用外部Bean来运算;

    @Component
    public class PersonProjectionHelper {
    
        public String getInfo(Person person){
            return person.toString();
        }
    }
    
  6. 可获取方法参数来参与运算。

我们在Repository的返回值中使用上面的接口:

public interface PersonRepository extends JpaRepository<Person, Long> {

    List<PersonProjectionInterface> findByNameIs(String name);

}

代码验证:

@Bean
CommandLineRunner interfaceProjectionQuery(PersonRepository personRepository){
   return args -> {
      List<PersonProjectionInterface> people = personRepository.findByNameIs("wyf");
      people.forEach(person -> {
         System.out.println(person.getName());
         System.out.println(person.getAddress());
         System.out.println(person.getAgeDesc());
         System.out.println(person.getCityDesc());
         System.out.println(person.getInfo());
         System.out.println(person.getHello("Hello"));
      });
   };
}

还可以通过类(DTO:Data Transfer Object 数据传输对象)来定制返回。

public class PersonDto {
    private final String name;
    private final Integer age;

    public PersonDto(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

我们可以使用Lombok的lombok.Value注解来简化上面的声明:

@Value
public class PersonDto {
    String name;
    Integer age;
}

在Repository声明方法:

public interface PersonRepository extends JpaRepository<Person, Long> {

    List<PersonDto> findByNameEquals(String name);

}

代码验证:

@Bean
CommandLineRunner classProjectionQuery(PersonRepository personRepository){
   return args -> {
      List<PersonDto> people = personRepository.findByNameEquals("wyf");
      people.forEach(System.out::println);
   };
}

还可以动态的选择返回的类型,在Repository可以用范型来定义返回值,并通过参数中指定返回的确定类型。

public interface PersonRepository extends JpaRepository<Person, Long> {

    <T> Collection<T> findByNameAndAge(String name, Integer age, Class<T> type);

}

代码验证:

 @Bean
CommandLineRunner dynamicProjectionQuery(PersonRepository personRepository){
   return args -> {
      Collection<Person> people1 = personRepository.findByNameAndAge("wyf", 35, Person.class);
      Collection<PersonProjectionInterface> people2 = personRepository.findByNameAndAge("wyf", 35, PersonProjectionInterface.class);
      Collection<PersonDto> people3 = personRepository.findByNameAndAge("wyf", 35, PersonDto.class);
      people1.forEach(person -> {
         System.out.println(person.getName());
         System.out.println(person.getAddress());
      });
      people2.forEach(personProjectionInterface -> {
         System.out.println(personProjectionInterface.getHello("Hello"));
         System.out.println(personProjectionInterface.getInfo());
      });
      people3.forEach(personDto -> {
         System.out.println(personDto.getName());
         System.out.println(personDto.getAge());
      });
   };
}

新书推荐:

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html
在这里插入图片描述

主要包含目录有:

第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和屁股里(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。

猜你喜欢

转载自blog.csdn.net/wiselyman/article/details/106417702