2013-12-19 54 views
0

我不得不從數據庫中檢索數據的方法:如何獲得的數據沒有得到「無法初始化代理 - 沒有會話」異常

public static List<ClassA> getAll() { 
    Session session = HibernateUtil.getSessionFactory().openSession(); 
    Transaction tx = null; 
    try { 
     tx = session.beginTransaction(); 
     Criteria criteria = session.createCriteria(ClassA.class); 
     List result = criteria.list(); 
     tx.commit(); 
     return result; 
    } catch (HibernateException ex) { 
     transactionRollBack(tx); 
     log.error(ex.getMessage()); 
    } finally { 
     session.close(); 
    } 
    return null; 
} 

用例:

List<ClassA> results = getAll(); 
for (ClassA result : results) { 
    System.out.println(result); //"could not initialize proxy - no Session" is thrown here 
} 

如果我理解正確的Hibernate文檔,這是因爲會話已關閉。但是我怎樣才能獲得數據和關閉會話(因爲它需要在下一個即將開始的事務之前關閉)?

更新

這裏是ClassA的內容包括toString()

@Entity 
@Table(name = "classA") 
public class ClassA implements Serializable { 

    private static final long serialVersionUID = 5163856045361200311L; 
    private int id; 
    private String name; 

    private Set<ClassB> classB = new HashSet<ClassB>(0); 

    public ClassA() {} 
    public ClassA(int id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public ClassA(String name) { 
     this.name = name; 
    } 

    public ClassA(ClassA classA) { 
     this.id = classA.getId(); 
     this.name = classA.getName(); 
    } 

    @Id 
    @GeneratedValue(strategy = AUTO) 
    @Column(name = "id", nullable = false, unique = true) 
    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    @Column(name = "name") 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @OneToMany(fetch = LAZY, mappedBy = "classA_id") 
    public Set<ClassB> getClassB() { 
     return classB; 
    } 

    public void setClassB(Set<ClassB> classB) { 
     this.classB = classB; 
    } 

    @Override 
    public String toString() { 
     return "ClassA{ id=" + id + ", name='" + name + ", classB =" + classB + '}'; 
    } 
} 

看來這個問題是與ClassB,但我不明白它是什麼。下面是ClassB

@Entity 
@Table(name = "classB") 
public class ClassB implements Serializable{ 

    private static final long serialVersionUID = -8481028941663340911L; 
    private int id; 
    private Date date; 
    private ClassA classA_id; 
    private int classA_counter; 

    public ClassB() {} 

    public ClassB(ClassB rec) { 
     this.id = rec.getId(); 
     this.date = rec.getDate(); 
     this.classA_id = rec.getClassA_id(); 
     this.classA_counter = rec.classA_counter(); 
    } 

    @Id 
    @GeneratedValue 
    @Column(name = "id", nullable = false) 
    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    @Temporal(DATE) 
    @Column(name = "date") 
    public Date getDate() { 
     return date; 
    } 

    public void setDate(Date date) { 
     this.date = date; 
    } 

    @ManyToOne(fetch = LAZY) 
    @JoinColumn(name = "classA_id", nullable = false) 
    public ClassA getCLassA_id() { 
     return classA_id; 
    } 

    public void setClassA_id(ClassA classA_id) { 
     this.classA_id = classA_id; 
    } 

    @Column(name = "classA_counter", columnDefinition = "int default 0") 
    public int getClassA_counter() { 
     return classA_counter; 
    } 

    public void setClassA_counter(int classA_counter) { 
     this.classA_counter = classA_counter; 
    } 

    @Override 
    public String toString() { 
     return "ClassB { id=" + id + ", date=" + date + ", classA_id=" + classA_id.getName() + ", classA_counter=" + classA_counter +'}'; 
    } 
} 

回答

1

的問題是,所述toString()方法,它是隱含由

System.out.println(result); 

嘗試調用還沒有被裝入由getAll()方法ClassA的實體的訪問的關聯。修復toString)方法,以便它只訪問保證存在的數據。

如果您確實需要在會話關閉後訪問某個關聯,請確保已通過查詢或致電Hibernate.initialize(classAInstance.getAssociationThatMustBeLoaded())加載該關聯。

+0

我更新了我的消息。我的'toString()'實現有什麼問題? – Dragon

+0

重新閱讀我的答案。 ClassA調用的toString()嘗試打印它包含的一組ClassB實例的內容。所以Hibernate試圖加載這個集合。但會議閉幕。所以你會得到這個例外。不要從ClasA的toString()方法中打印ClassB的集合。 –

0

的問題是在ClassB的,但這個問題的根源是在ClassA.getClassB()。我改變了從懶惰到渴望的抓取策略,一切都開始按照我的預期完美工作:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "classA_id") 
public Set<ClassB> getClassB() { 
    return classB; 
} 
相關問題