• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

상속 관계 엔티티 로직을 분기처리 하는 법?

23.07.07 10:09 작성 23.07.07 10:13 수정 조회수 226

0

안녕하세요 상속관계 엔티티를 다루는 방법에 대해 궁금한 점 있어 질문 드립니다

상속관계의 엔티티가 존재하고, 자식 엔티티마다 서비스 로직이 다를 수 있을 때 어떻게 분기처리하는지 알고 싶어 질문 드립니다

 

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "base_type")
public abstract class BaseEntity {

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

    private String title;

    private String description;

    @Column(name = "base_type", updatable = false, insertable = false, length = 30)
    private String baseType;

    protected BaseEntity(Long id, String title, String description) {
        this.id = id;
        this.title = title;
        this.description = description;
    }
}

@Entity
@DiscriminatorValue(value = "FIRST")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class FirstEntity extends BaseEntity{

    private int like;

    @Builder
    public FirstEntity(Long id, String title, String description, int like) {
        super(id, title, description);
        this.like = like;
    }
}        

@Entity
@DiscriminatorValue(value = "SECOND")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class SecondEntity extends BaseEntity {

    private String redirectUrl;

    @Builder
    public SecondEntity(Long id, String title, String description, String redirectUrl) {
        super(id, title, description);
        this.redirectUrl = redirectUrl;
    }
}


이러한 상속구조 엔티티가 있고, 두 자식의 서비스 로직이 다를 수 있을 때
컨트롤러에서 분기처리를 어떻게 하는지 알고 싶습니다

@RestController
@RequiredArgsConstructor
@RequestMapping("/v1/test")
public class TestController {

    private final TestService testService;

    @GetMapping
    public void findEntity(@RequestParam String type) {

        if(type.equalsIgnoreCase("first")) {

        } else if(type.equalsIgnoreCase("second")) {
            
        }
        //...
        //...
        //...
    }
}

만약 이러한 구조로 간다면, 자식클래스가 늘어났을 때 또 if문을 추가해야해서 효율적이지 못할 것 같아서요!

지금 생각한 것은 상태 패턴을 이용하면 어떨까 하는데, 이게 좋은지 잘 모르겠습니다..

public interface BaseContext {

    boolean support(String type);

    void executeFind();
}

이렇게 인터페이스를 만들어주고

@Component
public class FirstContext implements BaseContext{

    private static final String TYPE = "FIRST";
    private final FirstService firstService;

    public FirstContext(FirstService firstService) {
        this.firstService = firstService;
    }

    @Override
    public boolean support(String type) {
        return TYPE.equalsIgnoreCase(type);
    }

    @Override
    public void executeFind() {
        firstService.find();
    }
}

자식클래스의 상태를 구현하는 클래스를 만들어주고

@RestController
@RequiredArgsConstructor
@RequestMapping("/v1/test")
public class TestController {
    private final List<BaseContext> contexts;

    @GetMapping
    public void findEntity(@RequestParam String type) {

        BaseContext findContext = contexts.stream()
                .filter(context -> context.support(type))
                .findAny()
                .orElseThrow(() -> new IllegalStateException("Error"));
        
        findContext.executeFind();
    }
}

컨트롤러에서는 이렇게 받아주면

자식 엔티티가 늘어나도 if-else를 하지 않아도 된다고 생각했습니다

다만, 자식 엔티티가 추가될 때 마다 Context를 추가해야 한다는 점과

Context가 Service를 바라보고있어 Service가 수정되면 Context와 Service 2가지 모두 수정해야한다는 점이 마음에 걸립니다

보통 상속관계의 엔티티를 다룰 때 어떤식으로 분기처리를 하나요??

강사님이 아니시더라도 다른 수강생분들의 의견도 달아주시면 좋겠습니다!!

답변 2

·

답변을 작성해보세요.

0

David님의 프로필

David

2023.07.09

안녕하세요. skehdxhd님, 공식 서포터즈 David입니다.

여러가지 방법이 있겠지만 map을 사용하여 if-else를 걷어내는 방법도 있으니 참고해 주세요.

https://stackoverflow.com/q/38292023 - Use of HashMap을 참고

감사합니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.07.09

안녕하세요, 인프런 AI 인턴이에요.

상속 관계 엔티티를 다룰 때, 자식 엔티티마다 서비스 로직이 다를 경우 분기 처리를 하는 방법은 다양합니다. 여러가지 방법 중에 몇 가지를 소개해드릴게요.

  1. 팩토리 메서드 패턴을 사용하기
    팩토리 메서드 패턴은 객체 생성을 처리하는 패턴으로, 각 자식 엔티티에 대한 팩토리 메서드를 제공하여 각각의 객체를 생성할 수 있도록 합니다. 그 후, 이를 사용하여 해당 자식 엔티티의 로직을 호출할 수 있습니다.

  2. 추상화 인터페이스를 사용하기
    자식 엔티티마다 다른 로직을 처리해야 할 경우, 엔티티들의 공통된 부분을 추상화하여 인터페이스로 정의한 후, 자식 엔티티에서 이를 구현하도록 합니다. 이후에는 해당 인터페이스를 사용하여 분기처리를 할 수 있습니다.

  3. 동적 디스패치를 사용하기
    자바의 다형성 특성을 이용하여 동적 디스패치를 사용할 수 있습니다. 엔티티들을 동일한 부모 클래스나 인터페이스로 참조하고, 각 엔티티에 대한 메서드를 오버라이딩하여 서비스 로직을 구현합니다. 이렇게 하면 실행 시점에 엔티티의 타입에 따라 적절한 메서드가 호출됩니다.

위의 방법들 중에서 가장 적합한 방법을 선택하여 사용하시면 됩니다. 어떤 방법이 가장 적합한지는 프로젝트 구조와 성격에 따라 다를 수 있으므로, 상황에 맞게 선택해주세요.

더 자세한 내용은 구체적인 상황을 알려주시면 더 도움을 드릴 수 있을 것 같아요. 추가로 궁금한 점이 있다면 언제든지 질문해주세요. 좋은 결과 있기를 바라요!