简体   繁体   中英

stackoverflow error during json conversion (hibernate bi-directional mapping)

I have two entity classes: User class with a list of questions, and Question class with a User attribute

User class declaration:

 @Entity
    @Table(schema="test",name="so_user")
    public class User {
    private List<Question> questions;
    //other attributes
            @OneToMany(cascade=CascadeType.ALL)
        @PrimaryKeyJoinColumn   
        public List<Question> getQuestions() {
            return questions;
        }
    //.. other methods
    }   

Question class declaration:

@Entity
@Table(schema="test")
public class Question {
private User askedBy;
//other attributes
  @ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
  @PrimaryKeyJoinColumn
  public User getAskedBy() {
    return askedBy;
  }

//.. other methods
}   

When i try to convert a user object to Json using the Gson library , it gives stackoverflow error . reason: user has a list of questions and each question in turn has a user attribute (used to have bi-directional mapping in hibernate).

test code :

public class MappingTest {
    public static void main(String[] args) {
        List<User> users = null;
        User user = null;
        //populate some users
        for (int i = 0; i < 10; i++) {
            if (i == 0)
                users = new ArrayList<User>();
            user = new User();
            List<Question> questions = null;
            Question question = null;
            //create dummy questions
            for (int questionCount = 0; questionCount < 5; questionCount++) {
                if(questionCount==0)
                    questions = new ArrayList<Question>();
                question = new Question();
                question.setAskedBy(user);
                System.out.println("question added is "+question);
                questions.add(question);
            }
            user.setQuestions(questions);
            users.add(user);
            System.out.println("user added is "+user);
        }
        //TODO
        System.out.println(users);
        Gson gson = new Gson();
        System.out.println(gson.toJson(users));

    }
}

console log:

Exception in thread "main" java.lang.StackOverflowError
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuffer.append(Unknown Source)
    at java.io.StringWriter.write(Unknown Source)
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:534)
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402)
    at com.google.gson.stream.JsonWriter.value(JsonWriter.java:495)
    at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:268)
    at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:253)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)

Put Jackson API in your ( com.fasterxml.jackson ) application and use this annotations in realationship

@JsonBackReference to inversed Classes (Lists or sets in case 1-To-N).

@JsonManagedReference to mappedBy classes (Single object in case 1-To-N).

In your case

@OneToMany(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn
@JsonManagedReference   
public List<Question> getQuestions() {
     return questions;
}

______________________________________


@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@PrimaryKeyJoinColumn
@JsonBackReference
public User getAskedBy() {
    return askedBy;
}

You need to print json with Jackson (not gson).

it works with me with bidirectional recursion in serialization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM