Spring:为什么普通和@ResponseBody控制器生成不同的代码?

时间:2014-10-11 21:14:37

标签: java json spring hibernate rest

我有两个班级:

/* ------------------------------------------------------ */
@Entity
@Table(name="ABC")
@NamedQuery(name="Abc.findAll", query="SELECT c FROM Abc c")
public class Abc implements Serializable {

    @Id @Column(unique=true, nullable=false)
    private int id;

    @ManyToOne
    @JoinColumn(name="def_id", nullable=false)
    private Def def;

    // getters and setters...

}
/* ------------------------------------------------------ */
@Entity
@Table(name = "DEF")
@NamedQuery(name = "Def.findAll", query = "SELECT c FROM Def c")
public class Def implements Serializable {

    @Id @Column(unique = true, nullable = false)
    private int id;

    @OneToMany(mappedBy = "def")
    private List<Abc> abc;

    public Def() {
    }
    // getters and setters...
}
/* ------------------------------------------------------ */

AbcDef有许多关联关系。

我需要从类Abc生成HTML表和JSON。我在控制器中有以下代码:

@RequestMapping(value="/page", method=RequestMethod.GET) // HTML table
public String getPage(Model model) {
    List<Abc> abc = AbcManager.findAll();
    model.addAttribute("abc", abc);
    return "abc";
}

@RequestMapping(value="/json", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) // JSON (REST API)
public @ResponseBody List<Abc> getJson() {
    List<Abc> abc = AbcManager.findAll();
    return abc;
}

如果我转到网址/page,一切正常。但是,如果我转到网址/json,我会收到此错误:

Oct 11, 2014 11:01:19 ODP. org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring] in context with path [/project] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net.example.project.entity.Def.nodes, could not initialize proxy - no Session] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net.example.project.entity.Def.nodes, could not initialize proxy - no Session

问题出在哪里?我不希望输出中包含所有Def的列表。 “普通”控制器适合我,但不是控制器。为什么呢?

我该如何解决?

2 个答案:

答案 0 :(得分:2)

只是猜测,因为我不确切地知道/page显示什么,但恕我直言,因为在/page中,您只显示Abc对象列表,每个对象都有{{1}我假设Def的加载是急切的(不是懒惰的)。因此,当您将模型传递给视图时,所有内容都已从数据库中提取

但杰克逊更加聪明并试图通过所有关系尽可能深入。因此,它会收到Def的列表,但每个都有Abc(如上所述),但Def列有Def,杰克逊试图找到列表放在Abc的输出中。当事务结束时,Hibernate没有Session,所以Exception。

您必须在Def中为Json序列化添加注释,以声明Def不应序列化。

答案 1 :(得分:0)

我删除了杰克逊JSON映射器。

现在我使用 org.json.simple 手动创建JSON,一切正常。