본문 바로가기
넓고 얕은 데이터베이스 지식/RDBMS

뷰(View)에 대해 알아보고 엔티티(Entity) 객체와 매핑해보자.

by 황원용 2024. 1. 30.
728x90

📌 MySQL에서의 뷰(View)

  • 뷰(View)는 가상의 테이블로 하나 이상의 테이블로부터 개발자가 미리 유도한 결과 집합을 보여준다.
  • 데이터를 실제로 저장하지 않고 쿼리를 실행할 때마다 기본 테이블에서 데이터를 가져와서 결과를 생성한다.
  • 기존 테이블을 커스텀한, 읽기 전용의 테이블이라고 볼 수 있으며 매번 뷰가 참조하는 실제 테이블에 수정, 삭제 등의 쿼리가 있을 때마다 변경된 결과로 갱신된다.
  • 일반적으로 뷰를 통해 데이터를 수정하거나 삭제하는 것은 불가능하며 수정 작업은 해당하는 기본 테이블에서 직접 수행되어야 한다.
    • MySQL의 경우 옵션을 이용하여 수정이 가능하기는 하나 기존 데이터의 가공과 조회를 위한 용도로 활용하는 것이 적합하다.
  • 데이터의 가공, 필터링, 보안 설정 등 다양한 용도로 활용된다.

 

🤗 뷰의 장점

데이터의 가공과 가상의 테이블을 통한 필터링

  • 예를 들어 여러 개의 테이블에 분산되어 있는 데이터를 뷰를 통해 하나의 테이블처럼 조회할 수 있다.
  • 또한, 뷰를 사용하여 복잡한 조인 연산을 단순화하고 필요한 컬럼만 선택하여 조회할 수 있다.

데이터 보안 설정

  • 예를 들어 사용자에게 특정 컬럼만 보여주고 다른 컬럼은 가려야 하는 경우 뷰를 생성하여 필요한 컬럼만 노출시킬 수 있다.

데이터의 일관성

  • 여러 개의 테이블을 조인하여 뷰를 생성하면 데이터의 중복을 피하고 일관된 결과를 얻을 수 있다.
  • 만약 테이블의 구조가 변경되더라도 뷰는 그대로 유지되므로 기존의 쿼리들도 수정할 필요가 없다. 

 

📖 뷰 테이블 생성 예시

CREATE VIEW department1_employees AS
SELECT * FROM employees WHERE department_id = 1;

 

 

🛠️ JPA를 이용하여 뷰(View)와 엔티티(Entity) 객체 매핑하기

member 테이블

  • member 테이블에는 선수명과 나이 성별 정보가 있으며 각 선수마다 소속된 팀의 외래키가 있다.

 

team 테이블

  • team 테이블에는 연고지와 팀명이 있다.

 

Member 엔티티

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;

    @Column
    private String name;

    @Column
    private int age;
    @Enumerated(EnumType.STRING)
    private Sex sex;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;
}
  • team과 membersms 다대일 매핑이 되어있다.

 

🛠️ 위의 두 테이블을 이용해 view를 만들어보자.

CREATE VIEW SQL문 

CREATE VIEW test_view AS
SELECT m.member_id, m.name as player_name, m.age, m.sex, t.name as team_name, t.city
FROM member m INNER JOIN team t
ON m.team_id = t.team_id;

 

생성된 뷰

  • view를 이용하여 위의 member 테이블과 각 member의 team 정보를 한 데 모아 볼 수 있게 되었다.

 

엔티티와 매핑하기

import org.springframework.data.annotation.Immutable;


@Getter
@Entity
@Table(name = "test_view")
@Immutable
public class View {

    @Id
    private Long memberId;

    private String playerName;

    private int age;

    @Enumerated(EnumType.STRING)
    private Sex sex;

    private String teamName;

    private String city;
}
  • 사실 View라고 해서 일반 테이블 매핑과 크게 다르지 않다.
  • 엔티티 클래스명과 실제 View 명이 다르다면 @Table 애너테이션으로 view 이름과 맞춘다.
  • @Immutable로 해당 테이블이 읽기 전용임을 명시한다.
  • 한 가지 고려해야 할 사항은 엔티티 매핑을 위해서는 반드시 기본키를 설정해야 한다는 것이다.
    • db 레벨에서 view는 기본키를 가지지 않지만 JPA를 이용하는 서버 레벨에서 매핑 시 기본키 설정이 필수적이다.
    • 해결 방법은 간단하다. view 테이블에서 기본키로 설정할 컬럼과 매핑되는 필드에 @Id를 붙이거나 하나의 필드를 기본키로 설정할 수 없는 경우 두 개 이상의 필드를 묶어 복합키를 설정하면 된다.

 

📜 결과

@RestController
@RequiredArgsConstructor
public class SearchController {


    private final ViewRepository viewRepository;
    
    @GetMapping("/views")
    public ResponseEntity<?> getSearchResults() {
    
    	List<View> searchList = viewRepository.findAll();

        ViewDto.ResponseDtoList response = new ViewDto.ResponseDtoList();
        response.setResponseDtoList(searchList);
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
}
  • JPA 기본 제공 메서드인 findAll()을 사용하여 전체 조회를 해보았다.

 

  • 위의 조회 로직을 사용하여 HTTP 요청을 날려보면 view의 전체 데이터가 정상적으로 조회됨을 확인할 수 있다.

 

 

 

참고

뤼튼

https://velog.io/@sierra9707/TIP-View-목적의-Entity-객체를-만드는-법

728x90