programing

잭슨 JSON과 휴지 상태 JPA의 무한 재귀 문제

prostudy 2022. 8. 3. 21:00
반응형

잭슨 JSON과 휴지 상태 JPA의 무한 재귀 문제

쌍방향 어소시에이션이 있는 JPA 오브젝트를 JSON으로 변환하려고 하면, 계속 취득됩니다.

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)

제가 찾은 것은 기본적으로 쌍방향 관련성을 피하는 것으로 끝나는 이 스레드뿐입니다.이 봄 벌레에 대한 해결 방법을 알고 있는 사람 있나요?

----- EDIT 2010-07-24 16:26:22 -----

코드니펫:

비즈니스 오브젝트 1:

@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Trainee extends BusinessObject {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "name", nullable = true)
    private String name;

    @Column(name = "surname", nullable = true)
    private String surname;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<BodyStat> bodyStats;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<Training> trainings;

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    private Set<ExerciseType> exerciseTypes;

    public Trainee() {
        super();
    }

    //... getters/setters ...
}

비즈니스 오브젝트 2:

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class BodyStat extends BusinessObject {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "height", nullable = true)
    private Float height;

    @Column(name = "measuretime", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date measureTime;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name="trainee_fk")
    private Trainee trainee;
}

컨트롤러:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Controller
@RequestMapping(value = "/trainees")
public class TraineesController {

    final Logger logger = LoggerFactory.getLogger(TraineesController.class);

    private Map<Long, Trainee> trainees = new ConcurrentHashMap<Long, Trainee>();

    @Autowired
    private ITraineeDAO traineeDAO;
     
    /**
     * Return json repres. of all trainees
     */
    @RequestMapping(value = "/getAllTrainees", method = RequestMethod.GET)
    @ResponseBody        
    public Collection getAllTrainees() {
        Collection allTrainees = this.traineeDAO.getAll();

        this.logger.debug("A total of " + allTrainees.size() + "  trainees was read from db");

        return allTrainees;
    }    
}

JPA-연수생 DAO의 구현:

@Repository
@Transactional
public class TraineeDAO implements ITraineeDAO {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public Trainee save(Trainee trainee) {
        em.persist(trainee);
        return trainee;
    }

    @Transactional(readOnly = true)
    public Collection getAll() {
        return (Collection) em.createQuery("SELECT t FROM Trainee t").getResultList();
    }
}

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">
    <persistence-unit name="RDBMS" transaction-type="RESOURCE_LOCAL">
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate"/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <!-- <property name="dialect" value="org.hibernate.dialect.HSQLDialect"/>         -->
        </properties>
    </persistence-unit>
</persistence>

Json Ignore Properties [2017 업데이트]:

이제 JsonIgnoreProperties사용하여 속성의 시리얼화를 억제하거나(시리얼라이제이션 중에) 읽은 JSON 속성의 처리를 무시할 수 있습니다.이것이 당신이 찾고 있는 것이 아니라면 아래를 계속 읽어주세요.

(이 점을 지적해 주신 As Zammel Alaa Eddine에게 감사드립니다).


JsonManagedReference 및 JsonBackReference

Jackson 1.6에서는 시리얼라이제이션 중에 getters/setters를 무시하지 않고 무한 재귀 문제를 해결하기 위해 두 개의 주석을 사용할 수 있습니다(및).

설명.

잭슨이 올바르게 동작하기 위해서는 stackoverflow 에러의 원인이 되는 infite 루프를 피하기 위해 관계의 양쪽 중 하나를 시리얼화하지 마십시오.

(당신의 참조을 가져갑니다.Set<BodyStat> bodyStatsJson과 같은 스토리지 형식으로 변환합니다.이 프로세스를 마샬링 프로세스라고 합니다.그런 다음, Jackson은 참조의 뒷부분을 찾습니다(즉,Trainee traineeBodyStat 클래스에서)를 사용하여 시리얼화하지 않고 그대로 둡니다.관계의 이 부분은 순방향 참조의 역직렬화(unmarshalling) 중에 재구성될 것이다.

코드를 다음과 같이 변경할 수 있습니다(쓸데없는 부분은 생략합니다).

비즈니스 오브젝트 1:

@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Trainee extends BusinessObject {

    @OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Column(nullable = true)
    @JsonManagedReference
    private Set<BodyStat> bodyStats;

비즈니스 오브젝트 2:

@Entity
@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class BodyStat extends BusinessObject {

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name="trainee_fk")
    @JsonBackReference
    private Trainee trainee;

이제 모든 것이 제대로 작동해야 합니다.

만약 더 많은 정보를 원하신다면, 저는 제 블로그인 Keenformatics에 Json과 Jackson Stackoverflow 문제에 대한 기사를 썼습니다.

편집:

확인할 수 있는 또 다른 유용한 주석은 @JsonIdentity입니다.정보: 잭슨이 오브젝트를 시리얼화할 때마다 오브젝트에 ID(또는 사용자가 선택한 다른 속성)를 추가하여 매번 오브젝트를 완전히 "스캔"하지 않도록 합니다.이 기능은 상호 연관된 개체 간에 체인 루프가 있는 경우에 유용합니다(예:Order -> Order Line -> User -> Order 반복)

이 경우 개체의 속성을 두 번 이상 읽어야 할 수 있습니다(예: 동일한 판매자를 공유하는 제품이 더 많은 제품 목록에서). 이 주석으로 인해 읽을 수 없습니다.항상 firebug 로그를 보고 Json 응답을 확인하고 코드 내에서 무슨 일이 일어나고 있는지 확인할 것을 권장합니다.

출처:

하면 .@JsonIgnore사이클을 끊습니다(참조).

합니다.org.codehaus.jackson.annotate.JsonIgnore (버전)com.fasterxml.jackson.annotation.JsonIgnore(일부러)

새로운 주석 @JsonIgnoreProperties를 사용하면 다른 옵션의 많은 문제가 해결됩니다.

@Entity

public class Material{
   ...    
   @JsonIgnoreProperties("costMaterials")
   private List<Supplier> costSuppliers = new ArrayList<>();
   ...
}

@Entity
public class Supplier{
   ...
   @JsonIgnoreProperties("costSuppliers")
   private List<Material> costMaterials = new ArrayList<>();
   ....
}

이렇게 해서문서합니다.
http://springquay.blogspot.com/2016/01/new-approach-to-solve-json-recursive.htmlhttpspringquay.blogspot.com/2016/01/.html

잭슨 2.0 2.0+를 사용할 수 .@JsonIdentityInfo은 나의 더 가 있었다.@JsonBackReference ★★★★★★★★★★★★★★★★★」@JsonManagedReference그것은 나에게 문제가 있었고 문제를 해결하지 못했다.하다

@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@traineeId")
public class Trainee extends BusinessObject {

@Entity
@Table(name = "ta_bodystat", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@bodyStatId")
public class BodyStat extends BusinessObject {

효과가 있을 거야

또한 Jackson 1.6은 양방향 참조를 처리하는 데 도움이 됩니다.찾고 있는 것 같습니다(이 블로그 엔트리에서도 기능에 대해 언급하고 있습니다).

또한 2011년 7월 현재 "jackson-module-hibernate"도 있어 휴지 상태의 오브젝트를 처리하는 데 도움이 될 수 있습니다.다만, 반드시 이 오브젝트(주석이 필요)를 취급하는 것은 아닙니다.

이제 Jackson은 필드를 무시하지 않고 사이클을 회피할 수 있게 되었습니다.

Jackson - 양방향 관계를 가진 엔티티의 직렬화(회피 주기)

이건 나한테 완벽하게 잘 작동했어.부모 클래스에 대한 참조를 언급하는 자식 클래스에 @JsonIgnore 주석을 추가합니다.

@ManyToOne
@JoinColumn(name = "ID", nullable = false, updatable = false)
@JsonIgnore
private Member member;

정상 작동 잭슨과 함께 작업할 때 Json 무한 재귀 문제 해결

이것이 1대 다 및 다대 다 매핑에서 제가 한 일입니다.

@ManyToOne
@JoinColumn(name="Key")
@JsonBackReference
private LgcyIsp Key;


@OneToMany(mappedBy="LgcyIsp ")
@JsonManagedReference
private List<Safety> safety;

저에게 가장 좋은 해결책은@JsonView각 시나리오별로 특정 필터를 만듭니다.,도할 수 .@JsonManagedReference ★★★★★★★★★★★★★★★★★」@JsonBackReference단, 소유자가 항상 소유측을 참조하고 그 반대도 아닌 하나의 상황에만 대한 하드코드화된 솔루션입니다.다른 시리얼라이제이션시나리오에서 Atribute의 주석을 달리해야 하는 경우는 할 수 없습니다.

문제

이번에는 두 , 즉 ㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴCompany ★★★★★★★★★★★★★★★★★」Employee이들 사이에 주기적인 의존관계가 있는 경우:

public class Company {

    private Employee employee;

    public Company(Employee employee) {
        this.employee = employee;
    }

    public Employee getEmployee() {
        return employee;
    }
}

public class Employee {

    private Company company;

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }
}

'연재하다'를 사용해서 입니다.ObjectMapper(스프링 부트):

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class CompanyTest {

    @Autowired
    public ObjectMapper mapper;

    @Test
    public void shouldSaveCompany() throws JsonProcessingException {
        Employee employee = new Employee();
        Company company = new Company(employee);
        employee.setCompany(company);

        String jsonCompany = mapper.writeValueAsString(company);
        System.out.println(jsonCompany);
        assertTrue(true);
    }
}

이 코드를 실행하면 다음과 같은 정보를 얻을 수 있습니다.

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)

'@JsonView'를 사용한 솔루션

@JsonView그럼 필터를 사용하여 오브젝트를 시리얼화할 때 포함할 필드를 선택할 수 있습니다.필터는 식별자로 사용되는 클래스 참조일 뿐입니다.먼저 필터를 만듭니다.

public class Filter {

    public static interface EmployeeData {};

    public static interface CompanyData extends EmployeeData {};

} 

이치노@JsonView을 사용법 실제로 '하다', '주석하다', '주석하다', '주석하다', '주석하다' 이렇게 요.Company 링크:

public class Company {

    @JsonView(Filter.CompanyData.class)
    private Employee employee;

    public Company(Employee employee) {
        this.employee = employee;
    }

    public Employee getEmployee() {
        return employee;
    }
}

및 테스트를 변경하여 시리얼라이저가 View를 사용하도록 합니다.

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class CompanyTest {

    @Autowired
    public ObjectMapper mapper;

    @Test
    public void shouldSaveCompany() throws JsonProcessingException {
        Employee employee = new Employee();
        Company company = new Company(employee);
        employee.setCompany(company);

        ObjectWriter writter = mapper.writerWithView(Filter.CompanyData.class);
        String jsonCompany = writter.writeValueAsString(company);

        System.out.println(jsonCompany);
        assertTrue(true);
    }
}

이은, 「무한재귀」의 문제에 대해서, 「무한재귀」의 코멘트가 하고 있기 입니다.이것은, 유저가 명시적으로 코멘트가 붙은 어트리뷰트를 시리얼 하고 싶다고 말하고 있기 때문입니다.@JsonView(Filter.CompanyData.class).

했을 때Employee는, 주석이 붙어 있지 않은 것을 확인하고, 시리얼화를 무시합니다.또한 REST API를 통해 전송할 데이터를 선택할 수 있는 강력하고 유연한 솔루션도 있습니다.

에서는 REST 메서드에 원하는 REST 컨트롤러 메서드에 주석을 달 수 .@JsonView시리얼화는 투과적으로 반환 객체에 적용됩니다.

확인할 필요가 있는 경우에 사용하는 Import는 다음과 같습니다.

import static org.junit.Assert.assertTrue;

import javax.transaction.Transactional;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

import com.fasterxml.jackson.annotation.JsonView;

시리얼화 시 휴지 상태의 초기화 문제를 처리하기 위해 특별히 설계된 잭슨 모듈(Jackson 2용)이 출시되었습니다.

https://github.com/FasterXML/jackson-datatype-hibernate

의존관계를 추가합니다(Hibernate 3과 Hibernate 4에는 다른 의존관계가 있습니다).

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-hibernate4</artifactId>
  <version>2.4.0</version>
</dependency>

그런 다음 잭슨의 ObjectMapper를 초기화할 때 모듈을 등록합니다.

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate4Module());

문서화는 현재 좋지 않습니다.사용 가능한 옵션에 대해서는 Hibernate4 Module 코드를 참조하십시오.

@JsonIgnoreProperties가 정답입니다.

다음과 같은 것을 사용합니다:

@OneToMany(mappedBy = "course",fetch=FetchType.EAGER)
@JsonIgnoreProperties("course")
private Set<Student> students;

내 경우, 다음과 같이 관계를 바꾸면 충분했다.

@OneToMany(mappedBy = "county")
private List<Town> towns;

대상:

@OneToMany
private List<Town> towns;

또 다른 관계는 그대로였다.

@ManyToOne
@JoinColumn(name = "county_id")
private County county;

@ManyToOne 엔티티에서는 @JsonBackReference를 사용하고 엔티티 클래스를 포함하는 @onetomany에서는 @JsonManagedReference를 사용해야 합니다.

@OneToMany(
            mappedBy = "queue_group",fetch = FetchType.LAZY,
            cascade = CascadeType.ALL
        )
    @JsonManagedReference
    private Set<Queue> queues;



@ManyToOne(cascade=CascadeType.ALL)
        @JoinColumn(name = "qid")
       // @JsonIgnore
        @JsonBackReference
        private Queue_group queue_group;

모든 장소에서 com.fasterxml.jackson을 사용해야 합니다.나는 그것을 알아내기 위해 많은 시간을 들였다.

<properties>
  <fasterxml.jackson.version>2.9.2</fasterxml.jackson.version>
</properties>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${fasterxml.jackson.version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${fasterxml.jackson.version}</version>
</dependency>

'아예'를 사용합니다.@JsonManagedReference ★★★★★★★★★★★★★★★★★」@JsonBackReference.

마지막으로 모델을 JSON에 직렬화할 수 있습니다.

import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(model);

나도 같은 문제를 만났다.하였습니다.@JsonIdentityInfo의 »ObjectIdGenerators.PropertyGenerator.class너너제제

이것이 저의 해결책입니다.

@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Trainee extends BusinessObject {
...

@JsonIgnore를 사용할 수 있지만 외부 키 관계로 인해 액세스할 수 있는 json 데이터는 무시됩니다.따라서 외부 키 데이터(대부분 필요한 시간)를 다시 쿼리하면 @JsonIgnore는 도움이 되지 않습니다.이 경우, 아래의 해결 방법을 따르십시오.

BodyStat 클래스가 다시 연습생 개체를 참조하기 때문에 무한 재귀가 발생합니다.

BodyStat

@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="trainee_fk")
private Trainee trainee;

연습생

@OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Column(nullable = true)
private Set<BodyStat> bodyStats;

따라서 연습생에서 의 부분을 코멘트/삭제해야 합니다.

분석을 더 한 결과 동일한 문제가 발생했는데, @JsonBackReference를 OneToMany 주석으로 유지하는 것만으로 매핑된 엔티티를 얻을 수 있다는 것을 알게 되었습니다.

@Entity
@Table(name = "ta_trainee", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Trainee extends BusinessObject {

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "id", nullable = false)
private Integer id;

@Column(name = "name", nullable = true)
private String name;

@Column(name = "surname", nullable = true)
private String surname;

@OneToMany(mappedBy = "trainee", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Column(nullable = true)
@JsonBackReference
private Set<BodyStat> bodyStats;

중요: ROMBOK를 사용하는 경우 Set, List 등의 컬렉션 속성을 제외하도록 하십시오.

다음과 같이 합니다.

@EqualsAndHashCode(exclude = {"attributeOfTypeList", "attributeOfTypeSet"})

DTO 패턴 생성 클래스 연습생을 사용할 수 있습니다.동면 상태 없이 DTO를 실행하며 잭슨 매퍼를 사용하여 연습생을 연습생으로 변환할 수 있습니다.DTO 및 빙고 오류 메시지 삭제:)

속성을 무시할 수 없는 경우 필드의 가시성을 수정해 보십시오.우리의 경우, 오래된 코드가 여전히 엔티티와 함께 엔티티를 전송하고 있었기 때문에, 제 경우는 다음과 같이 수정했습니다.

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private Trainee trainee;

내 경우엔, 어떤 이유에서인지, 세트와는 작동하지 않았어.List로 변경하여 @JsonIgnore와 @ToString을 사용해야 했습니다.제외하여 작동시킵니다.

목록으로 세트 바꾸기:

//before
@OneToMany(mappedBy="client")
private Set<address> addressess;

//after
@OneToMany(mappedBy="client")
private List<address> addressess;

그리고 @JsonIgnore와 @ToString을 추가합니다.주석 제외:

@ManyToOne
@JoinColumn(name="client_id", nullable = false)
@JsonIgnore
@ToString.Exclude
private Client client;

「 」를 사용하고 @JsonManagedReference,@JsonBackReference ★★★★★★★★★★★★★★★★★」@JsonIgnore주석은 일부 필드를 무시하고 잭슨 JSON으로 무한 재귀 문제를 해결합니다.

,을 @JsonIdentityInfo값을 수 에 이 값을 사용하는 .@JsonIdentityInfo석입니니다다

@JsonIdentityInfo(generator= ObjectIdGenerators.UUIDGenerator.class, property="@id")

자세한 내용은 이 기사 https://www.toptal.com/javascript/bidirectional-relationship-in-json를 참조하십시오.@JsonIdentityInfo석입니니다다

이 게시물: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion에는 자세한 설명이 있습니다.

Jackson을 이전 버전에서 사용하는 경우 @jsonmanagedreference + @jsonbackreference를 사용해 보십시오.Jackson이 2 이상일 경우(1.9도 내가 알기로는 작동하지 않음) @JsonIdentity를 사용해 보십시오.대신 정보를 입력합니다.

이 문제가 있었습니다만, 엔티티에서 주석을 사용하고 싶지 않았기 때문에 클래스용 컨스트럭터를 작성함으로써 해결했습니다.이 컨스트럭터는 이 엔티티를 참조하는 엔티티에 대한 참조를 가지고 있지 않아야 합니다.이 시나리오로 합시다.

public class A{
   private int id;
   private String code;
   private String name;
   private List<B> bs;
}

public class B{
   private int id;
   private String code;
   private String name;
   private A a;
}

, 「」가 .B ★★★★★★★★★★★★★★★★★」A@ResponseBody무한 루프를 일으킬 수 있습니다., 의 클래스로 수 .entityManager이것처럼.

"select new A(id, code, name) from A"

이 클래스는 컨스트럭터와의 클래스입니다.

public class A{
   private int id;
   private String code;
   private String name;
   private List<B> bs;

   public A(){
   }

   public A(int id, String code, String name){
      this.id = id;
      this.code = code;
      this.name = name;
   }

}

, 이 솔루션에는 몇 가지 제약사항이 있습니다.이러한 제약사항은 컨스트럭터에서는 리스트 bs를 참조하지 않았습니다.이는 적어도 버전 3.6.10에서는 휴지 상태가 허용되지 않기 때문입니다.마지막으로 뷰에 두 엔티티를 모두 표시해야 할 경우 다음을 수행합니다.

public A getAById(int id); //THE A id

public List<B> getBsByAId(int idA); //the A id.

이 솔루션의 또 다른 문제는 속성을 추가하거나 제거할 경우 생성자와 모든 쿼리를 업데이트해야 한다는 것입니다.

Spring Data Rest를 사용하는 경우 순환 참조와 관련된 모든 엔티티에 대한 리포지토리를 생성하여 문제를 해결할 수 있습니다.

나는 늦게 왔는데 벌써 너무 긴 실타래야.하지만 저도 몇 시간 동안 이 문제를 해결하기 위해 노력했고, 또 다른 예로 제 사례를 들겠습니다.

Json Ignore, Json Ignore Properties 및 Back Reference 솔루션을 모두 사용해 보았습니다만, 이상하게도 그것들이 받아들여지지 않았습니다.

저는 Lombok을 사용했는데, 이것이 컨스트럭터를 만들고 toString을 덮어쓰기 때문에 방해가 될 수 있다고 생각했습니다(stackoverflowerror 스택의 toString).

마지막으로, 이것은 Lombok의 잘못이 아닙니다.저는 데이터베이스 테이블에서 NetBeans 자동 생성 JPA 엔티티를 사용하였습니다.그리고 생성된 클래스에 추가된 주석 중 하나는 @XmlRootElement였습니다.내가 그것을 제거하자 모든 것이 작동하기 시작했다.아, 그렇군요.

요점은 다음과 같이 @JsonIgnore를 setter 메서드에 배치하는 것입니다.저 같은 경우에는요.

Township.java

@Access(AccessType.PROPERTY)
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="townshipId", nullable=false ,insertable=false, updatable=false)
public List<Village> getVillages() {
    return villages;
}

@JsonIgnore
@Access(AccessType.PROPERTY)
public void setVillages(List<Village> villages) {
    this.villages = villages;
}

마을.자바

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "townshipId", insertable=false, updatable=false)
Township township;

@Column(name = "townshipId", nullable=false)
Long townshipId;

같은 문제에 직면해 있습니다.jsonbackref와 jsonmanagedref를 추가하여 @override와 hashCode 메서드가 동일한지 확인하십시오.이것으로 이 문제가 확실히 해결됩니다.

언급URL : https://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue

반응형