복붙노트

[SPRING] Spring 데이터를 느슨하게로드할지 여부 지정하기

SPRING

Spring 데이터를 느슨하게로드할지 여부 지정하기

엔티티에 게으른 가져 오기 유형 컬렉션이 있습니다. 그리고 엔티티에 액세스하기 위해 Spring Data (JpaRepository)를 사용하고 있습니다.

@Entity
public class Parent{
@Id
private Long id;

    @OneToMany(mappedBy = "parentId", fetch = FetchType.LAZY)
    private Set<Child> children;
}

서비스 클래스에 두 개의 함수가 필요하고 현재 구현은 다음과 같습니다.

RestController에서 "Parent"엔티티를 반환 할 때 예외가 throw됩니다.

@RequestMapping("/parent/{parentId}")
public Parent getParent(@PathVariable("parentId") Long id)
{
    Parent p= parentService.getParent(id);//ok till here
    return p;//error thrown when converting to JSON
}

해결법

  1. ==============================

    1.유스 케이스에 따라 동일한 도메인 모델에 대해 다른 JSON 표현을 허용하려는 경우 DTO가 필요없이 다음을 수행 할 수 있습니다.

    유스 케이스에 따라 동일한 도메인 모델에 대해 다른 JSON 표현을 허용하려는 경우 DTO가 필요없이 다음을 수행 할 수 있습니다.

    https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

    또는 다음의 '스프링 데이터 REST의 투영법'섹션을 참조하십시오.

    https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra#projections-in-spring-data-rest

  2. ==============================

    2.RestController는 Parent 엔터티 대신 ParentDTO를 반환해야합니다. ParentDTO는 Transactional 서비스 메서드에서 채울 수 있습니다.

    RestController는 Parent 엔터티 대신 ParentDTO를 반환해야합니다. ParentDTO는 Transactional 서비스 메서드에서 채울 수 있습니다.

  3. ==============================

    3.JSON serializer가 모든 속성을 이미 초기화해야하므로 예외가 발생합니다. 따라서 부모를 반환해야하는 모든 REST 컨트롤러는 속성을 먼저 초기화해야합니다.

    JSON serializer가 모든 속성을 이미 초기화해야하므로 예외가 발생합니다. 따라서 부모를 반환해야하는 모든 REST 컨트롤러는 속성을 먼저 초기화해야합니다.

    @RequestMapping("/parent/{parentId}")
    public Parent getParent(@PathVariable("parentId") Long id) {
        return parentService.getParentWithChildren(id);
    }
    

    getParentWithChildren 서비스 메소드는 트랜잭션 내에서 실행되며 트랜잭션이 커밋 될 때 연관된 Hibernate Session은 닫힌다. 이것은 Hibernate Session이 여전히 열려있는 동안 (Service 메소드 내부에서) 당신이 모든 프로퍼티를 초기화해야한다는 것을 의미한다.

    또한 Spring Data 엔티티 그래프 지원을 사용할 수 있습니다.

    @Entity
    @NamedEntityGraphs(@NamedEntityGraph(name = "Parent.children", attributeNodes = @NamedAttributeNode("children")))
    public class Parent{
    @Id
    private Long id;
    
        @OneToMany(mappedBy = "parentId", fetch = FetchType.LAZY)
        private Set<Child> children;
    }
    

    그리고 getParentWithChildren 메소드는 다음과 같습니다.

    @Repository
    public interface ParentRepository extends CrudRepository<Parent, Long> {
    
        @EntityGraph(value = "Parent.children", type = EntityGraphType.LOAD)
        Parent getParentWithChildren(Long parentId);
    }
    

    따라서 다음을 구현할 필요조차 없습니다.

    이 메소드는 Spring 데이터에서 제공 할 수 있습니다.

  4. ==============================

    4.우선, 당신은 Child Java 클래스를 우리에게 보여주지 않았다 : 나는 그 속성이 parentId이고 parent가 아니라고 희망한다.

    우선, 당신은 Child Java 클래스를 우리에게 보여주지 않았다 : 나는 그 속성이 parentId이고 parent가 아니라고 희망한다.

    public class Child {
        @ManyToOne
        private Parent parentId;
    }
    

    해결책 1 : 도메인 계층을 클라이언트 / 브라우저로 전송하기 위해 두 번째 계층의 DTO (단순 POJO 클래스)를 사용해야한다는 코드가 실제로 정확합니다. 그렇게하지 않으면 Lazy 예외를 해결 한 후에 Parent에서 Child 로의 순환 종속성에 문제가 생기고 JSON marshaller (Jackson)는 Child, 그 부모, 다시 자식을 인코딩하려고 시도 할 것입니다. 그때 다시 부모님과 같이. DTO의 예는 다음과 같습니다.

    public class ParentDto {
        private Long id;
        private String prop1;
    
        public ParentDto(Parent parent) {
                this.id = parent.id;
                this.prop1 = parent.prop1;
                //...other properties
        }
    
        //here come all getters for the properties defined above.
    }
    

    해결 방법 2 : 공용 속성 Parent.getChildren ()에 @JsonIgnore를 사용하면 Parent 인스턴스를 정렬 할 때 Jackson이 자식을 인코딩하지 않도록 할 수 있습니다.

  5. from https://stackoverflow.com/questions/28896287/specifying-whether-or-not-to-lazily-load-with-spring-data by cc-by-sa and MIT license