3

我对使用 Spring MVC 3.1.2 和 Jackson 2 的错误感到抓狂。

我有以下模型类:

@Entity
@Table(name = "USER")
@JsonIgnoreProperties(ignoreUnknown=true)
public class User implements Serializable
{
    @Id
    @SequenceGenerator(name = "USER_ID", sequenceName = "USER_ID_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID")
    private Long id;

    @Column(length = 50, nullable = false)
    private String firstName;

    @Column(length = 50, nullable = false)
    private String lastName;

    @ManyToMany
    @JoinTable(name = "FRIENDS",
        joinColumns = @JoinColumn(name = "personId"),
        inverseJoinColumns = @JoinColumn(name = "friendId")
    )
    @JsonManagedReference
    private List<User> friends;

    @ManyToMany
    @JoinTable(name="FRIENDS",
        joinColumns=@JoinColumn(name="friendId"),
        inverseJoinColumns=@JoinColumn(name="personId")
    )
    @JsonIgnore
    private List<User> friendOf;

    // Other attributes and methods... 
}

当我得到一个 User 实例时,它被 Jackson 正确序列化。但是当我尝试获取包含朋友的 User 实例时,会引发以下异常:

org.hibernate.LazyInitializationException:未能延迟初始化角色集合:com.frooid.model.User.friends,没有会话或会话已关闭

我正在使用单个 HQL 获取此实例:

select u from User u left join fetch u.friends f where u.id = :id

谢谢大家!

4

3 回答 3

5

ToMany 关联默认是延迟加载的。这意味着您的用户的朋友只会在调用friends列表的方法时从数据库中加载。

这种延迟加载只能在用于加载用户的会话打开时发生。因此,如果您在未加载好友列表的情况下从事务方法返回用户,则会话将关闭,并且尝试加载好友列表将导致您遇到异常。

因此,如果客户端需要加载好友列表,则可以使用 HQL 获取好友,或者在服务方法内部,通过调用列表上的方法或调用Hibernate.initialize(user.getFriends()).

编辑:因为你在你的 HQL 中有一个 fetch,它应该可以工作。另一个问题是双向关联被映射了两次:一次在friends场上,一次在friendOf场上。mappedBy必须使用以下属性将其中一个关联标记为另一个关联:

@ManyToMany(mappedBy = "friends")
@JsonIgnore
private List<User> friendOf;
于 2012-11-25T20:23:18.327 回答
5

尝试使用OpenSessionInViewFilterwhile 这用于访问视图中的惰性初始化字段,它可能会保持会话打开,让 Jackson 能够访问集合。

OpenSessionInViewFilterHibernate Session 绑定到线程以完成请求的整个处理。用于“在视图中打开会话”模式,即允许在 Web 视图中延迟加载,尽管原始事务已经完成。

在 Web.xml 中

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

API 文档

于 2012-11-25T20:20:45.753 回答
0

我有类似的问题。@JsonView({NewClass1.class,NewClass2.class})方法是创建一个新类(视图)并在定义属性的实体中的每个属性中添加此类。您可以选择要加载的变量作为响应的一部分,并将类包含在@JsonView. 就这么简单!

于 2015-06-03T10:08:33.437 回答