복붙노트

[SPRING] 최대 절전 모드 jpa를 사용하여 JSON을 직렬화 및 비 직렬화하여 JSON 응답으로 부모 개체를 자식 개체에 넣습니다.

SPRING

최대 절전 모드 jpa를 사용하여 JSON을 직렬화 및 비 직렬화하여 JSON 응답으로 부모 개체를 자식 개체에 넣습니다.

봄 프레임 워크, 최대 절전 모드 및 JSON으로 나머지 웹 응용 프로그램을 개발 중입니다. 아래 두 엔티티가 있다고 가정하십시오.

BaseEntity.java

@MappedSuperclass
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id" )
public abstract class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    public long getId() {
        return id;
    }
}

University.java

 public class University extends BaseEntity {

      private String uniName;

       @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,orphanRemoval = true)
      @JoinColumn(name = "university_id")
        private List<Student> students=new ArrayList<>();
    // setter an getter
    }

Student.java

    public class Student extends BaseEntity{

        private String stuName;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "university_id",updatable = false,insertable = false)   
        private University university;

    // setter an getter
        }

내가 휴식 API를 호출하면 대학이 기대했던대로 모든 일이 잘 작동하지만, 나머지 API를 호출하면 학생을 간절히 열거합니다. JSON 응답은

[
   {
    "id": 1,
    "stuName": "st1",
    "university": {
        "id": 1,
        "uniName": "uni1"
                 }
    },
    {
        "id": 2,
        "stuName": "st2",
        "university": 1
    }
]

하지만 내 원하는 응답은 다음과 같습니다.

[
    {
        "id": 1,
        "stutName": "st1",
        "university": 
        {
         "id": 1,
        "uniName": "uni1"
        }
    },
    {
        "id": 2,
        "stutName": "st2",
        "university": 
        {
         "id": 1,
        "uniName": "uni1"
        }
    }

업데이트 1 : 내 최대 절전 모드 주석 잘 작동합니다. JSON 문제가 있습니다.

요구 사항 :

원하는 종류의 직렬화 또는 JSON 구성을 사용하여 원하는 응답을 일치시킬 수 있습니까?

업데이트 2 :

@JsonIdentityInfo를 제거하고 학생 측을 아래와 같이 편집하면됩니다.

json 응답은 여전히 ​​동일하다. 위에서 언급 한 내 원하는 응답이 필요합니다.

감사

해결법

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

    1.@JsonIdentityInfo를 기본 클래스에서 제거하면 대학 객체가 ID 만 serialize합니다.

    @JsonIdentityInfo를 기본 클래스에서 제거하면 대학 객체가 ID 만 serialize합니다.

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

    2.@JoinColumn을 Student 엔터티에 추가 할 수 있습니까?

    @JoinColumn을 Student 엔터티에 추가 할 수 있습니까?

    @ManyToOne(fetch = FetchType.EAGER)  
    @JoinColumn(name = student_id")
    

    대학 엔티티 클래스의 외래 키도 확인하십시오. 외래 키는 다른 엔티티에서 가져온 것입니까? @JoinColumn (name = "university_id", foreignKey = @ForeignKey (name = "student_id")) ??

    그렇지 않으면 "mappedBy"도 사용할 수 있습니다.

    @JoinColumn(name = "university_id", mappedBy="university")
            private List<Student> students=new ArrayList<>();
    
  3. ==============================

    3.추가하고 체크 할 수 있습니다.

    추가하고 체크 할 수 있습니다.

    대학

    public class University {
    
    @Fetch(value = FetchMode.SELECT)
    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "university_id")
    @JsonIgnore 
     private List<Student> students;
    
    }
    

    학생

    public class Student{
    @ManyToOne
    @JoinColumn(name = "university_id", insertable = true, updatable = true, nullable = true)
    private University university;
    }
    
  4. ==============================

    4.JSON에 University.students를 포함하고 싶지 않다는 것을 이해합니다.

    JSON에 University.students를 포함하고 싶지 않다는 것을 이해합니다.

    University.students를 다른 상황에서 직렬화해야하는 경우 http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion에 읽기를 제공하십시오. 양방향 관계를 다루는 다른 옵션이 설명되어 있습니다.

  5. ==============================

    5.getter 메소드에 @jsonignore를 추가하십시오. @jsonProperty를 필드에 추가합니다. 처럼

    getter 메소드에 @jsonignore를 추가하십시오. @jsonProperty를 필드에 추가합니다. 처럼

    @JsonProperty(access = Access.READ_ONLY)
    private String password;
    

    최근 잭슨에게 Readonly와 writeonly 같은 기능을 추가했습니다. 당신은 이것을 참조 할 수 있습니다 : http://fasterxml.github.io/jackson-annotations/javadoc/2.6/com/fasterxml/jackson/annotation/JsonProperty.Access.html

  6. ==============================

    6.대학 속성에 대한 주석으로 @JsonRawValue를 사용해 볼 수도 있습니다. 발생한 문제는 참조 축소로 인해 발생합니다. 동일한 대학에서 두 번이기 때문에 직렬 변환기는 똑똑하고 두 번째로 참조를 반환합니다.

    대학 속성에 대한 주석으로 @JsonRawValue를 사용해 볼 수도 있습니다. 발생한 문제는 참조 축소로 인해 발생합니다. 동일한 대학에서 두 번이기 때문에 직렬 변환기는 똑똑하고 두 번째로 참조를 반환합니다.

    편집 : toString () :

    @Override
    public String toString() {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(this);
    }
    
  7. ==============================

    7.관계를 매핑하는 방법은 "잘 작동하는"경우에도 양방향 관계에 대한 jpa 규격을 준수하지 않습니다. 이 질문 및 관련 답변을 참조하십시오.

    관계를 매핑하는 방법은 "잘 작동하는"경우에도 양방향 관계에 대한 jpa 규격을 준수하지 않습니다. 이 질문 및 관련 답변을 참조하십시오.

    요약하면, 관계의 소유자는 many-to-one이고 일대 다면은 mappedBy로 주석됩니다. 관계를 소유하고있는 일대 다 측면을 가진 매핑 솔루션은 평소 / 권장되지는 않습니다 (위의 답변에서 설명한대로). 기술적으로 가능합니다. (@manyToOne 쪽은 "updatable = false"와 같은 속성을 사용자의 예에서 누락시킵니다.)

    그런 다음, JPA와 최근의 Hibernate 버전에서, lazy loading 정책은 다음과 같다 :

     OneToMany: LAZY
     ManyToOne: EAGER
     ManyToMany: LAZY
     OneToOne: EAGER
    

    그래서이 기본 지연로드 정책을 사용하고 manyToOne 관계의 소유자를 변경하는 것이 좋습니다. 단일 대학 리소스 요청을 통해 모든 학생을 확보하는 것이 좋지 않은 것처럼 보입니다. (페이지 매김에 대해 들었습니까?)

    그렇게 함으로서 또한 @ JsonIgnore를 사용하여 마샬링 (Marshalling)에서 학생 컬렉션을 제외시키는 것이 트릭을 수행해야합니다.

  8. ==============================

    8.나는 똑같은 문제가 있었다. 최대 절전 모드 (또는 eclipselink)는 문제가되지 않습니다. JPA의 유일한 제약은 FetchType.EAGER입니다.

    나는 똑같은 문제가 있었다. 최대 절전 모드 (또는 eclipselink)는 문제가되지 않습니다. JPA의 유일한 제약은 FetchType.EAGER입니다.

    BaseEntity에서 표준 메소드를 추가했습니다.

    public String getLabel(){
       return "id:"+this.getId();
    }
    

    이 방법은 추상적 일 텐데, 나는 많은 수업을 받았고, 모든 것을 바꾸고 싶지 않았기 때문에 기본값을 추가했습니다.

    상위 엔티티 (이 경우 University)에서 메소드를 재정의하십시오.

    @Override
    public String getLabel{
        return this.uniName;
    }
    

    각 상위 클래스에 대해 특정 필드를 엔티티의 레이블로 사용하십시오.

    MyStandardSerializer를 정의하십시오.

    public class StandardJsonSerializer extends JsonSerializer<EntityInterface> {
    
    @Override
    public void serializeWithType(EntityInterface value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException, JsonProcessingException {
            serialize(value, jgen, provider); 
    }
    
    @Override
    public void serialize(EntityInterface value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("id", (long) value.getId());
        jgen.writeStringField("label", value.getLabel());
        jgen.writeEndObject();
    }
    

    }

    학생 클래스에서는 대학에서 다음을 추가합니다.

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "university_id",updatable = false,insertable = false)   
    @JsonSerialize(using=StandardJsonSerializer.class)
    private University university;
    

    이제 당신은 순환 성을 해결했습니다. 레이블이 필요할 때 상위 엔터티의 메서드를 재정의합니다. 특정 필드가 필요할 때 특정 Serializer를 작성하십시오.

  9. from https://stackoverflow.com/questions/46684015/json-serializing-and-deserializing-with-hibernate-jpa-to-have-parent-object-into by cc-by-sa and MIT license