hibernate 报错信息如下:
严重: Servlet.service() for servlet [spring2] in context with path [/convention] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.girltest.entity.Test2Boy.conventions, could not initialize proxy - no Session] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.girltest.entity.Test2Boy.conventions, could not initialize proxy - no Session
有问题的代码:
public Test2Boy getConventions(int id){
Convention c=new Convention();
c.setStatus(Constant2.NEWS_STATUS_ON);
Test2Boy test2Boy=(Test2Boy)super.getCurrentSession().createCriteria(clz)
.add(Restrictions.idEq(id))
.createAlias(Constant.property_conventions, "convention32")
.add(Restrictions.eq("convention32.status", Constant2.NEWS_STATUS_ON))
.uniqueResult();
return test2Boy;
}
说明:conventions 是Test2Boy的成员变量
报错的原因我也知道,因为
改为fetch = FetchType.EAGER 就好了.
但是我不想这样改.
因为查询Test2Boy列表时,不需要把conventions也查询出来.
所以我特意设置fetch方式为lazy.
但是在Test2Boy 的详情页面需要把conventions 查询出来.
Test2Boy的实体类如下:
package com.girltest.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
/***
*
* @author huangweii
* 2015年12月27日
*/
@Entity
@Table(name = "t_test_to_boy")
public class Test2Boy {
private int id;
/***
* 测试
*/
private String testcase;
/***
* 别名
*/
private String alias;
/***
* 别名
*/
private String alias2;
/***
* 最佳惯例
*/
private Convention best;
/***
* 所有惯例
*/
private List<Convention> conventions;
/***
* 更新时间
*/
protected String updateTime;
/***
* 热度 <br>
* 值越大,表示越受关注
*/
protected int stars;
/***
* 1:有效;2:被删除
*/
private int status;
@Column(name="update_time")
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public int getStars() {
return stars;
}
public void setStars(int stars) {
this.stars = stars;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTestcase() {
return testcase;
}
public void setTestcase(String testcase) {
this.testcase = testcase;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getAlias2() {
return alias2;
}
public void setAlias2(String alias2) {
this.alias2 = alias2;
}
@ManyToOne( fetch = FetchType.LAZY)
@JoinColumn(name = "best_convention_id")
public Convention getBest() {
return best;
}
public void setBest(Convention best) {
this.best = best;
}
@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name="t_mid_test_convention",
joinColumns={@JoinColumn(name="test_id")},
inverseJoinColumns={@JoinColumn(name="convention_id")}
)
@Fetch(FetchMode.SUBSELECT)
public List<Convention> getConventions() {
return conventions;
}
public void setConventions(List<Convention> conventions) {
this.conventions = conventions;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
怎么办呢?
解决方法:使用参数CriteriaSpecification.LEFT_JOIN
public Test2Boy getConventions(int id){
Convention c=new Convention();
c.setStatus(Constant2.NEWS_STATUS_ON);
Test2Boy test2Boy=(Test2Boy)super.getCurrentSession().createCriteria(clz)
.add(Restrictions.idEq(id))
.createAlias(Constant.property_conventions, "convention32",CriteriaSpecification.LEFT_JOIN)
.add(Restrictions.eq("convention32.status", Constant2.NEWS_STATUS_ON))
.uniqueResult();
return test2Boy;
}