티스토리 뷰

 

1. 엔티티 그대로 노출

    @GetMapping("/api/v1/simple-orders")
    public List<Order> orderV1(){
        List<Order> all = orderRepository.findAllByString(new OrderSearch());
        return all;
    }

 

엔티티를 그대로 노출할 경우 어떻게 될까?

 

이렇게 끝도 없는 json을 보게 될 것이다.

 

public class Order {

    @Id @GeneratedValue
    @Column(name= "order_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY) //order 입장에서는 여러개의 order에 하나의 회원이다.
    @JoinColumn(name = "member_id") //FK를 지정해준다.
    private Member member;
public class Member {

    @Id @GeneratedValue
    @Column(name="member_id")
    private Long id;

    @NotEmpty
    private String name;

    @Embedded // jpa 내장타입 일 수 있다는 표시
    private Address address;

    @OneToMany(mappedBy = "member") //하나의 member에서 여러개의 order이다. mappedBy를 연관관계의 주인을 지정한다. 주인인 order 클래스 쪽은 그대로 두고 아래의 무엇으로 지정이 되는지 필드명을 적어준다. 이곳의 값을 변경한다고 해서 fk값이 변경되지 않는다.
    private List<Order> orders = new ArrayList<>();

 

order와 member는 서로를 계속 불러오게끔 되어있기 때문이다.

 

해결 순서

    @JsonIgnore
    @OneToMany(mappedBy = "member") //하나의 member에서 여러개의 order이다. mappedBy를 연관관계의 주인을 지정한다. 주인인 order 클래스 쪽은 그대로 두고 아래의 무엇으로 지정이 되는지 필드명을 적어준다. 이곳의 값을 변경한다고 해서 fk값이 변경되지 않는다.
    private List<Order> orders = new ArrayList<>();

 

  1. 양방향 연관관계의 경우 한쪽은 JsonIgnore처리를 해줘야한다. 그러고 호출하면 2차 문제가 터진다

인터셉터바디 어쩌구 오류..

 

bytebuddy에 대한 오류가 나온다. bytebuddy는 프록시에 관한 오류인데

 

  • member에는 지연로딩이 걸려있다(FetchType.LAZY). 지연로딩의 경우 프록시 객체를 가짜로 넣어놓고 나중에 조회할 때에 진짜 객체로 갈아치우는 방식으로 진행된다. 그 가짜객체가 bytebuddy이므로 조회하지 않았다면 json으로 만들 때에 저 객체를 어떻게 할줄 몰라 발생하는 오류이다.

- 이럴 경우 하이버네이트 데이터 모듈을 설치해야 한다.

	implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'

(버전을 따로 적지 않으면 알아서 스프링 버전에 맞는 것으로 자동으로 설치 된다.)

package jpabook2.jpashop2;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Jpashop2Application {

	public static void main(String[] args) {
		SpringApplication.run(Jpashop2Application.class, args);
	}

	@Bean
	Hibernate5Module hibernate5Module(){
		return new Hibernate5Module();
	}
}

 

@bean으로 등록

 

스프링부트 3.0 이상

	implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5-jakarta'
package jpabook2.jpashop2;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.fasterxml.jackson.datatype.hibernate5.jakarta.Hibernate5JakartaModule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Jpashop2Application {

	public static void main(String[] args) {
		SpringApplication.run(Jpashop2Application.class, args);
	}

	@Bean
	Hibernate5JakartaModule hibernate5Module(){
		return new Hibernate5JakartaModule();
	}
}

 

-  이렇게 하면 문제를 해결할 수 있다.

 

만약 order 외에 연관관계의 내용을 가져오고 싶다면

    @GetMapping("/api/v1/simple-orders")
    public List<Order> orderV1(){
        List<Order> all = orderRepository.findAllByString(new OrderSearch());

        for (Order order : all) {
            order.getMember().getName(); //LAZY 강제 초기화
            order.getDelivery().getStatus(); //LAZY 강제 초기화
        }
        return all;
    }

강제로 연관관계를 초기화해서 가져오면 된다. 

 

하지만 아직 문제가 있다.

 

  • 절대 엔티티를 반환하면 안된다. 여러 문제가 있다. api 스펙이 바뀌면 사용 중인 고객들에게 모두 바꾸라 할 수 없는 노릇이며, 엔티티또한 바뀔 수 있다. 어떤 문제가 터질지 짐작 할 수가 없다.

2편에 계속..

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함