我对使用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...
}
当我获得一个用户的单个实例时,它被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
感谢大家!
答案 0 :(得分:5)
尝试使用OpenSessionInViewFilter
虽然这是为了访问视图中的延迟初始化字段,但可以让会话保持开放状态,以便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>
答案 1 :(得分:5)
默认情况下,ToMany关联是延迟加载的。这意味着在调用friends
列表的方法时,只会从数据库加载用户的文本。
这种延迟加载只能在用于加载用户的会话打开时发生。因此,如果您在没有加载好友列表的情况下从事务方法返回用户,则会话将被关闭,并且尝试加载freinds列表将导致您获得的异常。
因此,如果客户端需要加载freinds列表,则使用HQL获取朋友,或者通过调用列表上的方法或调用{{1}强制在服务方法内部对列表进行初始化}。
编辑:既然您在HQL中有一个提取,它应该可以工作。另一个问题是双向关联被映射两次:一次在Hibernate.initialize(user.getFriends())
字段上,一次在friends
字段上。其中一个关联必须使用friendOf
属性标记为另一个关联:
mappedBy
答案 2 :(得分:0)
我有类似的问题。方法是创建一个新类(视图),并在@JsonView({NewClass1.class,NewClass2.class})
中的每个属性上添加此类,在定义属性的实体中。您可以选择要作为响应的一部分加载的变量,并将该类包含在@JsonView
中。就这么简单!