Spring MVC 3.1.2 + Jackson 2:懒惰初始化集合时的LazyInitializationException - 没有关闭会话或会话

Mar*_*ino 3 spring json hibernate hql jackson

我对使用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... 
}
Run Code Online (Sandbox Code Playgroud)

当我获得一个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
Run Code Online (Sandbox Code Playgroud)

谢谢大家!

Kev*_*sox 5

尝试使用OpenSessionInViewFilterwhile这是为了访问视图中的延迟初始化字段,它可以使会话保持开放状态,以便Jackson能够访问该集合.

OpenSessionInViewFilter结合一个Hibernate会话给线程的请求的整个处理.用于"在视图中打开会话"模式,即允许在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>
Run Code Online (Sandbox Code Playgroud)

API文档


JB *_*zet 5

默认情况下,ToMany关联是延迟加载的.这意味着只有在调用friends列表方法时才会从数据库加载用户的文本.

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

因此,如果客户端需要加载freinds列表,则使用HQL获取朋友,或者通过调用列表上的方法或通过调用强制在服务方法内初始化列表Hibernate.initialize(user.getFriends()).

编辑:既然你有一个你的HQL中的提取,它应该工作.另一个问题是双向关联被映射两次:一次在friends场上,一次在friendOf场上.其中一个关联必须使用mappedBy属性标记为另一个关联:

@ManyToMany(mappedBy = "friends")
@JsonIgnore
private List<User> friendOf;
Run Code Online (Sandbox Code Playgroud)