欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

failed to lazily initialize a collection of role: , could not initialize proxy - no Session

程序员文章站 2022-04-11 17:13:30
...

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的成员变量
报错的原因我也知道,因为
failed to lazily initialize a collection of role: , could not initialize proxy - no Session
改为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;
    }