[Spring JPA #24] Spring JPA Projection

2021. 3. 26. 01:37 Spring Data/Spring Data JPA

 

| Spring JPA Projection

 

Spring JPA에서 제공하는 Projection 기능은 엔티티의 일부 데이터만을 가져오게 하는 기능입니다. Projection은 인터페이스 기반으로 구현되며 이 인터페이스를 가지고 Repository의 반환값에 명시하면 이 정보를 토대로 JPA가 해당 쿼리를 최적화해서 가져올 수 있거나 표현식을 사용하여 DB에서 데이터를 커스터마이징하여 가져올 수 있습니다.

 

| Spring JPA Projection 예제

 

프로젝트 구조

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── tutorial
│   │   │           └── springevent
│   │   │               ├── Application.java
│   │   │               ├── Comment.java
│   │   │               ├── CommentOnly.java
│   │   │               ├── CommentRepository.java
│   │   │               ├── CommentSummary.java
│   │   │               ├── PostController.java
│   │   │               ├── Post.java
│   │   │               └── PostRepository.java
│   │   └── resources
│   │       └── application.properties
│   └── test
│       └── java
│           └── com
│               └── tutorial
│                   └── springevent
│                       └── CommentRepositoryTest.java

 

의존성 관리

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

 

소스 코드 

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@Entity
@Data
public class Comment {

    @Id
    @GeneratedValue
    private Long id;

    private String comment;

    @ManyToOne
    private Post post;

    private int up;

    private int down;

    private boolean best;
}
@Entity
@Data
public class Post {

    @Id @GeneratedValue
    private Long id;

    private String title;

    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
}
public interface CommentOnly {

    String getComment();
}

 

  • Closed 프로젝션 인터페이스로서 하나의 Comment만을 가져오게 JPA에서 최적화시킬 수 있습니다.
public interface CommentSummary {

    String getComment();

    int getUp();

    int getDown();

    default String getVotes() {
        return getUp() + " " + getDown();
    }
}
  • Commnet, Up, Down 컬럼을 가져올 수 있고 이 두 컬럼을 조합해서 getVotes 메서드를 통해 기존값을 결합하여 데이터를 가져올 수 있습니다. 
public interface CommentRepository extends JpaRepository<Comment, Long> {

    <T> List<T> findByPost_Id(Long id, Class<T> type);
}
  • 제네릭을 통하여 같은 메서드로 데이터를 가져오는 Projection들을 한 메서드를 통해 데이터를 가져올 수 있게 합니다.
public interface PostRepository extends JpaRepository<Post, Long> {
}

 

테스트 코드

@RunWith(SpringRunner.class)
@DataJpaTest
public class CommentRepositoryTest {

    @Autowired
    CommentRepository commentRepository;

    @Autowired
    PostRepository posts;

    @Test
    public void getComment() {
        Post post = new Post();
        post.setTitle("jps");
        Post savedPost = posts.save(post);

        Comment comment = new Comment();
        comment.setComment("Hello World");
        comment.setPost(savedPost);
        comment.setUp(10);
        comment.setDown(1);
        Comment save = commentRepository.save(comment);

        commentRepository.findByPost_Id(savedPost.getId(), CommentSummary.class).forEach( c -> {
            System.out.println("==============");
            System.out.println(c.getVotes());
        });

        commentRepository.findByPost_Id(savedPost.getId(), CommentOnly.class).forEach( c -> {
            System.out.println("==============");
            System.out.println(c.getComment());
        });
    }
}

 

https://www.inflearn.com/course/스프링-데이터-jpa



출처: https://engkimbs.tistory.com/836?category=772527 [새로비]