当我们使用hibernate进行级联查询时,时有可能遇到级联查询的递归现象的。
例如:博文表和用户表
博文表字段:
博文id | 用户id | 博文标题 | ... |
---|
用户表字段:
用户id | 用户名 | ... |
---|
实体类:
博文实体类:
@Table(name = "blogs")
public class Blog implements Serializable{
private int bid;
private User user;
private String title;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getBid(){}
public void setBid(int bid){}
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "uid")
public User getUser(){}
public void setUser(User user){}
public String getTitle(){}
public void setTitle(String title){}
}
用户实体类:
@Entity
@Table(name = "users")
public class User implements Serializable{
private int uid;
private String username;
private Set<Blog> blogs;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getUid(){}
public void setUid(int uid){}
public String getUsername(){}
public void setUsername(String username){}
@OneToMany(cascade = CascadeType.ALL,mappedBy = "user",fetch = FetchType.EAGER)
public Set<Blog> getBlogs(){}
public void setBlogs(Set<Blog> blogs){}
}
我们知道,当我们想要查找某个博文的时候,总是希望把他的作者一起查询出来,所以我们在这里使用了级联查询,此时的fetch类型需要是FetchType.EAGER否则会查询不到User对象,并且会报No Session异常。这里是因为hibernate懒加载只保留一个get函数,不会真正的去级联查询,当你用到的时候再去帮你查询,但是当你用到的时候session已经关闭了,所以会报no session异常。当然,解决这个异常的一个好方法就是不使用懒加载。当我们设置了fetch=FetchType.EAFER时,hibernate就会在第一次加载博文的时候帮你把User加载出来,此时就会产生一个问题。我们需要加载一篇博文,而且我们仅仅是想把博文的作者加载出来,但是hibernate的级联查询不仅仅能帮我们把博文的作者查询出来,还能继续级联把这个作者的所有博文查询出来,当然这还不算,所有的博文都有一个User对象,hibernate还可以继续级联查询各个博文的作者,然后查询各个作者的每个博文.......其中还包括我们已经查询到的博文。
想象一下,假如我们有一个作者,他只写了一篇博文,那么当我们想要去查询这篇博文时,hibernate会加载作者信息,然后发现作者信息中blogs不为空,继续加载这个作者的博文信息(其实这个信息我们已经查询到了),之后继续递归,查询我们根本不想再让他查询的消息。
我们当然不希望这种情况发生,尤其是我们希望将数据以json形式发送到前端页面进行处理时,这种数据会造成json数据解析的死循环(但是对于hibernate本身好像并无影响,我猜可能hibernate是有一个级联查询的深度的,查到原因再更新)。
处理方法:
对数据进行处理,这种情况主要的问题出现在json数据传递上,若是有机会,可以使用懒加载进行处理。
若是需求不能满足懒加载进行处理,那么我们可以在获取数据后手动将递归值设置为null。
假如查询到的博文对象为blog,我们希望获取他的作者信息,但是不希望获取到作者以后的信息,可以这么设置:
blog.getUser.setBlogs(null);
这样可以获取到博文信息和作者信息,到作者信息一层递归就截止了。我们就可以轻松的向前台传递json数据。
网友评论