2015-09-02 9 views
10

Kiedy wiosna MVC spróbować przekształcić obiekt WZP, która ma dwukierunkową stowarzyszenie do JSON Jackson 2.6.1, ciśglenieskończonej rekurencji z Jackson JSON Spring MVC 4.2 i Hibernate JPA problem

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) 

a pierwsza jednostka jest:

import com.fasterxml.jackson.annotation.JsonManagedReference; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
... 

@Entity 
@Table(name = "user") 
public class User implements java.io.Serializable { 
    private Integer userId; 
    @JsonManagedReference 
    private UserClass userClass; 

@Id 
@GeneratedValue(strategy = IDENTITY) 
@Column(name = "userId", unique = true, nullable = false) 
public Integer getUserId() { 
    return this.userId; 
} 

@ManyToOne() 
@JoinColumn(name = "userClassId") 

public UserClass getUserClass() { 
    return this.userClass; 
} 
....... 
} 

drugi:

import com.fasterxml.jackson.annotation.JsonManagedReference; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
... 

@Entity 
@Table(name = "user_class") 
public class UserClass implements java.io.Serializable { 

private Integer userClassId; 
@JsonBackReference 
private List<User> users = new ArrayList<User>(0); 

@Id 
@GeneratedValue(strategy = IDENTITY) 
@Column(name = "userClassId", unique = true, nullable = false) 
public Integer getUserClassId() { 
    return this.userClassId; 
} 


@OneToMany(fetch = FetchType.LAZY, mappedBy = "userClass") 
public List<User> getUsers() { 
    return this.users; 
} 

i tu jest zależnościami:

<dependencies> 

     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>3.8.1</version> 
      <scope>test</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-webmvc</artifactId> 
      <version>4.2.0.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-orm</artifactId> 
      <version>4.2.0.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-oxm</artifactId> 
      <version>4.2.0.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.data</groupId> 
      <artifactId>spring-data-jpa</artifactId> 
      <version>1.8.2.RELEASE</version> 
      <exclusions> 
       <exclusion> 
        <groupId>org.springframework</groupId> 
        <artifactId>spring-aop</artifactId> 
       </exclusion> 
      </exclusions> 
     </dependency> 


     <dependency> 
      <groupId>javax.servlet</groupId> 
      <artifactId>servlet-api</artifactId> 
      <scope>provided</scope> 
      <version>2.5</version> 
     </dependency> 
     <dependency> 
      <groupId>javax.servlet</groupId> 
      <artifactId>jstl</artifactId> 
      <version>1.2</version> 
     </dependency> 

     <dependency> 
      <groupId>cglib</groupId> 
      <artifactId>cglib</artifactId> 
      <version>3.1</version> 
     </dependency> 

     <dependency> 
      <groupId>log4j</groupId> 
      <artifactId>log4j</artifactId> 
      <version>1.2.17</version> 
     </dependency> 

     <dependency> 
      <groupId>com.thoughtworks.xstream</groupId> 
      <artifactId>xstream</artifactId> 
      <version>1.4.8</version> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-core</artifactId> 
      <version>2.6.1</version> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.6.1</version> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.datatype</groupId> 
      <artifactId>jackson-datatype-hibernate4</artifactId> 
      <version>2.6.1</version> 
     </dependency> 



     <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>5.1.34</version> 
     </dependency> 

     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core</artifactId> 
      <version>4.3.10.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-entitymanager</artifactId> 
      <version>4.3.10.Final</version> 
     </dependency> 
     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-validator</artifactId> 
      <version>5.1.3.Final</version> 
     </dependency> 

     <dependency> 
      <groupId>org.apache.tiles</groupId> 
      <artifactId>tiles-core</artifactId> 
      <version>3.0.5</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.tiles</groupId> 
      <artifactId>tiles-jsp</artifactId> 
      <version>3.0.5</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.tiles</groupId> 
      <artifactId>tiles-api</artifactId> 
      <version>3.0.5</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.tiles</groupId> 
      <artifactId>tiles-template</artifactId> 
      <version>3.0.5</version> 
     </dependency> 

     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>jcl-over-slf4j</artifactId> 
      <version>1.7.12</version> 
     </dependency> 
     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-api</artifactId> 
      <version>1.7.12</version> 
     </dependency> 
     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-simple</artifactId> 
      <version>1.7.12</version> 
     </dependency> 

     <dependency> 
      <groupId>com.google.guava</groupId> 
      <artifactId>guava</artifactId> 
      <version>18.0</version> 
     </dependency> 


    </dependencies> 

użyłem „@JsonIgnore”, „@JsonIdentityInfo” i „XmlTransient” dla zapobiegania rekursji, ale oboje nie pracują i sprawozdanie serwera Ten błąd. Czy ktoś może mi pomóc?

Dzięki.

Edit: I ślad stosu:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: 
sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]-> 
org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]... . 
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: 
sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]-> 
org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]->org.hibernate.collection.internal.PersistentBag[0]->sss.com.model.User["userClass"]->sss.com.model.UserClass["users"]... . with root cause 
java.lang.StackOverflowError 
    at java.io.IOException.<init>(IOException.java:58) 
    at com.fasterxml.jackson.core.JsonProcessingException.<init>(JsonProcessingException.java:25) 
    at com.fasterxml.jackson.core.JsonProcessingException.<init>(JsonProcessingException.java:41) 
    at com.fasterxml.jackson.databind.JsonMappingException.<init>(JsonMappingException.java:143) 
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:689) 
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:149) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:111) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:24) 
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:656) 
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675) 
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157) 
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:656) 
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675) 
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:149) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:111) 
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:24) 
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:656) 
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675) 
... 

rozwiązany: W moim pierwotnym podmiotem mam 5 dwukierunkową relację, ale po prostu byłem odnotowany jeden związek. Powodem jest, że tomcat nie wydrukował wyjątku na stronie wyników i nie sprawdzam pliku dziennika tomcat.

+0

post pełna ślad stosu wyjątku. –

+0

Dodano ślad stosu. Dziękuję –

+0

Bezpłatna porada, nie używaj swoich jednostek JPA do generowania JSON, utwórz zestaw DTO używanych między frontent/services i datamodel, ułatwi ci to życie. –

Odpowiedz

16

Wystarczy umieścić @JsonIgnore

@JsonIgnore 
@OneToMany(fetch = FetchType.LAZY, mappedBy = "userClass") 
public List<User> getUsers() { 
    return this.users; 
} 

Ten obiekt będzie ignorować leniwy obciążenia i rozwiązać problem.

Aktualizacja

  • Według Udara Seneviratneanswer można obsługiwać bi-directional relationship przez @JsonManagedReference, @JsonBackReference.
+0

To też działa dla mnie.Ale nie rozumiem, dlaczego w pewnym momencie dla niektórych obiektów danych występuje nieskończona rekursja. – Brain

+1

@ Transakcja hibernacji sesji Springa znika po zakończeniu @ Blok transakcyjny kończy się, gdy jackson próbuje leniwego załadować użytkowników z wyjątku obiektu hibernacji proxy, który został zgłoszony jako sesja już zakończona. –

+0

dziękuję. To ma sens. Czy pomogłoby to użyć Hibernate.initialize (...), aby zapobiec temu błędowi? – Brain

0

Spróbuj dodać @XmlTransient adnotacji powyżej manytoone stronie odniesienia,

import com.fasterxml.jackson.annotation.JsonManagedReference; 
import javax.persistence.Entity; 
import javax.persistence.Table; 
... 

@Entity 
@Table(name = "user") 
public class User implements java.io.Serializable { 
private Integer userId; 
@JsonManagedReference 
private UserClass userClass; 

@Id 
@GeneratedValue(strategy = IDENTITY) 
@Column(name = "userId", unique = true, nullable = false) 
public Integer getUserId() { 
    return this.userId; 
} 

@XmlTransient 
@ManyToOne() 
@JoinColumn(name = "userClassId") 

    public UserClass getUserClass() { 
    return this.userClass; 
} 
....... 
} 
+1

Dodaję tę adnotację (@ javax.xml.bind.annotation.XmlTransient), ale znowu widzę ten błąd. Dziękuję za odpowiedź na moje pytanie. –

+0

Ok. Zgodnie z moim rozumieniem ten problem daje odwołanie cykliczne. Więc jeśli używasz adnotacji XmlTransient. to zignoruje pole od odpowiedzi. w tej adnotacji należy dodać wszystkie elementy, których użyto w wielu adnotacjach. spróbuj także usunąć adnotacje związane z jsonem (JsonManagedReference, JsonIgnore, JsonIdentityInfo itp.) –

Powiązane problemy