JsonMappingException的解决方案:懒惰地初始化集合而不使用@Jsonignore

时间:2015-06-04 16:47:57

标签: java json hibernate jpa jackson

我需要响应JSON作为输出。但它显示了异常

org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.sublime.np.entity.User.roles, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.sublime.np.entity.Question["user"]->com.sublime.np.entity.User["roles"])
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    at org.codehaus.jackson.map.ser.std.StdContainerSerializers$IndexedListSerializer.serializeContents(StdContainerSerializers.java:122)
    at org.codehaus.jackson.map.ser.std.StdContainerSerializers$IndexedListSerializer.serializeContents(StdContainerSerializers.java:71)
    at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1613)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:209)
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:143)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:89)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)

我在实体之间使用了这么多关系。 我的Qustion实体看起来像,

@Entity
public class Question {

    @Id
    @GeneratedValue
    private Integer id;

    @Size(min=5, message = "Title must be at least 5 characters !" )
    private String title;

    @Size(min=20, message = "Description must be at least 20 characters !" )
    private String description;

    private int upVote;

    private int downVote;

    @Column(name = "published_date")
    private Date publishedDate;

    @ManyToOne
    @JoinColumn(name="user_id")

    private User user;

    @OneToMany(mappedBy="question", cascade=CascadeType.REMOVE)
    private List<Answer> answers;

    @OneToMany(mappedBy="question", cascade=CascadeType.REMOVE) 
    private List<Comment> comments;

    @ManyToOne
    @JoinColumn(name="tag_id")
    private Tag tag;

当我使用@JsonIgnore注释时,它可以工作。但是从我关系中的json领域消失了。

@OneToMany(mappedBy="question", cascade=CascadeType.REMOVE)
    @JsonIgnore  
    private List<Answer> answers;

    @OneToMany(mappedBy="question", cascade=CascadeType.REMOVE)
    @JsonIgnore  
    private List<Comment> comments;

    @ManyToOne
    @JoinColumn(name="tag_id")
    @JsonIgnore  
    private Tag tag;

使用@JsonIgnore后的JSON,

[
  {
    "id": 1,
    "title": "ABC",
    "description": "ABC",
    "upVote": 0,
    "downVote": 0,
    "publishedDate": 1433436068000
  },
  {
    "id": 2,
    "title": "SQL Exception",
    "description": "ABC",
    "upVote": 0,
    "downVote": 0,
    "publishedDate": 1433436068000
  }
]

我的控制器,

@RequestMapping(value = "getquestion", method = RequestMethod.GET)
    public @ResponseBody List<Question> getQuestion() {
        List<Question> questions = questionService.getAll();
        return questions;
}

所以,我需要json与实体的所有领域。我怎么能得到它?任何想法?