2016-09-22 92 views
1

我使用hibernate創建休息api。我創建了一個方法來獲取表中的所有項目。Hibernate-未能懶洋洋地初始化一個角色集合:beans.Language.patients,無法初始化代理 - 沒有會話

public List<Language> getAllLanguages(Session session) { 
     List<Language> languages=(List<Language>)session.createQuery("from Language").list(); 
     return languages; 
} 

這是我Language.java

public class Language implements java.io.Serializable { 


    private Integer idlanguage; 
    private String language; 
    private Set<Patient> patients = new HashSet<Patient>(0); 

    public Language() { 
    } 


    public Language(String language) { 
     this.language = language; 
    } 
    public Language(String language, Set<Patient> patients) { 
     this.language = language; 
     this.patients = patients; 
    } 

    public Integer getIdlanguage() { 
     return this.idlanguage; 
    } 

    public void setIdlanguage(Integer idlanguage) { 
     this.idlanguage = idlanguage; 
    } 
    public String getLanguage() { 
     return this.language; 
    } 

    public void setLanguage(String language) { 
     this.language = language; 
    } 
    public Set<Patient> getPatients() { 
     return this.patients; 
    } 

    public void setPatients(Set<Patient> patients) { 
     this.patients = patients; 
    } 

} 

這是我Patient.java

// Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 


import beans.DiabetesType; 
import beans.Illness; 
import beans.Language; 
import beans.Reminder; 
import java.util.Date; 
import java.util.HashSet; 
import java.util.Set; 

/** 
* Patient generated by hbm2java 
*/ 
public class Patient implements java.io.Serializable { 

    private Integer idpatient; 
    private DiabetesType diabetesType; 
    private Language language; 
    private String customId; 
    private String diabetesOther; 
    private String firstName; 
    private String lastName; 
    private String userName; 
    private String password; 
    private Date dateCreated; 
    private Date lastUpdated; 
    private Set<Illness> illnesses = new HashSet<Illness>(0); 
    private Set<Reminder> reminders = new HashSet<Reminder>(0); 


    public Patient() { 
    } 

    public Patient(Integer idpatient, String password) { 
     this.idpatient = idpatient; 
     this.password = password; 
    }  

    public Patient(DiabetesType diabetesType, Language language, String customId, String firstName, String userName, String password, Date lastUpdated) { 
     this.diabetesType = diabetesType; 
     this.language = language; 
     this.customId = customId; 
     this.firstName = firstName; 
     this.userName = userName; 
     this.password = password; 
     this.lastUpdated = lastUpdated; 
    } 
    public Patient(DiabetesType diabetesType, Language language, String customId, String diabetesOther, String firstName, String lastName, String userName, String password, Date dateCreated, Date lastUpdated, Set<Illness> illnesses, Set<Reminder> reminders) { 
     this.diabetesType = diabetesType; 
     this.language = language; 
     this.customId = customId; 
     this.diabetesOther = diabetesOther; 
     this.firstName = firstName; 
     this.lastName = lastName;  
     this.userName = userName; 
     this.password = password; 
     this.dateCreated = dateCreated; 
     this.lastUpdated = lastUpdated; 
     this.illnesses = illnesses; 
     this.reminders = reminders; 
    } 

    public Integer getIdpatient() { 
     return this.idpatient; 
    } 

    public void setIdpatient(Integer idpatient) { 
     this.idpatient = idpatient; 
    } 
    public DiabetesType getDiabetesType() { 
     return this.diabetesType; 
    } 

    public void setDiabetesType(DiabetesType diabetesType) { 
     this.diabetesType = diabetesType; 
    } 
    public Language getLanguage() { 
     return this.language; 
    } 

    public void setLanguage(Language language) { 
     this.language = language; 
    } 
    public String getCustomId() { 
     return this.customId; 
    } 

    public void setCustomId(String customId) { 
     this.customId = customId; 
    } 
    public String getDiabetesOther() { 
     return this.diabetesOther; 
    } 

    public void setDiabetesOther(String diabetesOther) { 
     this.diabetesOther = diabetesOther; 
    } 
    public String getFirstName() { 
     return this.firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 
    public String getLastName() { 
     return this.lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getUserName() { 
     return this.userName; 
    } 

    public void setUserName(String userName) { 
     this.userName = userName; 
    } 
    public String getPassword() { 
     return this.password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 
    public Date getDateCreated() { 
     return this.dateCreated; 
    } 

    public void setDateCreated(Date dateCreated) { 
     this.dateCreated = dateCreated; 
    } 
    public Date getLastUpdated() { 
     return this.lastUpdated; 
    } 

    public void setLastUpdated(Date lastUpdated) { 
     this.lastUpdated = lastUpdated; 
    } 
    public Set<Illness> getIllnesses() { 
     return this.illnesses; 
    } 

    public void setIllnesses(Set<Illness> illnesses) { 
     this.illnesses = illnesses; 
    } 
    public Set<Reminder> getReminders() { 
     return this.reminders; 
    } 

    public void setReminders(Set<Reminder> reminders) { 
     this.reminders = reminders; 
    } 
} 

要點:豆類和映射反向從MySQL數據庫設計的,通過的NetBeans 。致電getAllLangauges時,我不需要獲得與patient相關的任何數據。我的language表只有2列,idlanguagelanguagePatient表有一個foriegn鍵language table

在休息API使用此方法之前,它沒有任何例外完美工作。但是當我在休息api中使用它時,它在那裏創造了一個複雜性。

我不在這裏使用註釋。我用hibernate反向工程嚮導來映射上面的實體。這是我的休息API方法。

@Path("/language") 
public class LanguageJSONService { 

    @GET 
    @Path("/getAllLanguages") 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<Language> getAllLanguages(){ 
     LanguageService languageService=new LanguageService(); 
     List<Language> list = languageService.getAllLanguages(); 
     return list; 
    } 
} 

這是我如何調用該方法的方式,

Client client = ClientBuilder.newClient(); 
List<Language> list = client.target("http://localhost:8080/simple_rest/rest") 
       .path("/language/getAllLanguages") 
       .request(MediaType.APPLICATION_JSON) 
       .get(new GenericType<List<Language>>() { 
       }); 

for (int i = 0; i < list.size(); i++) { 
     System.out.println("Id - " + list.get(i).getIdlanguage() + " Language - " + list.get(i).getLanguage()); 
} 

當我調用該方法,

failed to lazily initialize a collection of role: beans.Language.patients, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->beans.Language["patients"]) 

的發生。

有趣的是,如果我沒有關閉會話,那麼我會得到如下的輸出,這完全是別的,好像它試圖顯示它的外鍵表和它們的外鍵表等等......

[{"idlanguage":1,"language":"English","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients":[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType":{"iddiabetesType":1,"type":"Sever","patients": 
[{"idpatient":1,"diabetesType": 

對此問題有什麼想法?

更新

我的配置文件

的hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
    <session-factory> 
    <property name="show_sql">true</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/*****</property> 
    <property name="hibernate.connection.username">*****</property> 
    <property name="hibernate.c3p0.min_size">5</property> 
    <property name="hibernate.c3p0.max_size">20</property> 
    <property name="hibernate.c3p0.timeout">3000</property> 
    <property name="hibernate.c3p0.max_statements">50</property> 
    <property name="hibernate.c3p0.idle_test_period">300</property> 
    <property name="hibernate.c3p0.testConnectionOnCheckout">true</property> 
    <property name="hibernate.c3p0.preferredTestQuery">SELECT 1</property> 
    <property name="hibernate.connection.password">************</property> 
    <mapping resource="beans/Reminder.hbm.xml"/> 
    <mapping resource="beans/Food.hbm.xml"/> 
    <mapping resource="beans/Patient.hbm.xml"/> 
    <mapping resource="beans/Illness.hbm.xml"/> 
    <mapping resource="beans/Language.hbm.xml"/> 
    </session-factory> 
</hibernate-configuration> 

Language.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 --> 
<hibernate-mapping> 
    <class name="beans.Language" table="language" catalog="myglukose" optimistic-lock="version"> 
     <id name="idlanguage" type="java.lang.Integer"> 
      <column name="idlanguage" /> 
      <generator class="identity" /> 
     </id> 
     <property name="language" type="string"> 
      <column name="language" length="45" not-null="true" /> 
     </property> 
     <set name="patients" table="patient" inverse="true" lazy="true" fetch="select"> 
      <key> 
       <column name="language_idlanguage" not-null="true" /> 
      </key> 
      <one-to-many class="beans.Patient" /> 
     </set> 
    </class> 
</hibernate-mapping> 

這是我的病人映射文件,

Patient.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 --> 
<hibernate-mapping> 
    <class name="beans.Patient" table="patient" catalog="myglukose" optimistic-lock="version"> 
     <id name="idpatient" type="java.lang.Integer"> 
      <column name="idpatient" /> 
      <generator class="identity" /> 
     </id> 
     <many-to-one name="diabetesType" class="beans.DiabetesType" fetch="select"> 
      <column name="diabetes_type_iddiabetes_type" not-null="true" /> 
     </many-to-one> 
     <many-to-one name="language" class="beans.Language" fetch="select"> 
      <column name="language_idlanguage" not-null="true" /> 
     </many-to-one> 
     <property name="customId" type="string"> 
      <column name="custom_id" length="45" not-null="true" /> 
     </property> 
     <property name="diabetesOther" type="string"> 
      <column name="diabetes_other" length="45" /> 
     </property> 
     <property name="firstName" type="string"> 
      <column name="first_name" length="100" not-null="true" /> 
     </property> 
     <property name="lastName" type="string"> 
      <column name="last_name" length="100" /> 
     </property>   
     <property name="userName" type="string"> 
      <column name="user_name" length="45" not-null="true" /> 
     </property> 
     <property name="password" type="string"> 
      <column name="password" length="45" not-null="true" /> 
     </property> 
     <property name="dateCreated" type="timestamp"> 
      <column name="date_created" length="19" /> 
     </property> 
     <property name="lastUpdated" type="timestamp"> 
      <column name="last_updated" length="19" not-null="true"> 
       <comment>Stores the basic information of the patient</comment> 
      </column> 
     </property> 
     <set name="illnesses" table="illness" inverse="true" lazy="true" fetch="select"> 
      <key> 
       <column name="patient_idpatient" not-null="true" /> 
      </key> 
      <one-to-many class="beans.Illness" /> 
     </set> 
     <set name="reminders" table="reminder" inverse="true" lazy="true" fetch="select"> 
      <key> 
       <column name="patient_idpatient" not-null="true" /> 
      </key> 
      <one-to-many class="beans.Reminder" /> 
     </set> 
    </class> 
</hibernate-mapping> 
+1

@MWiesner:不是。您提到的鏈接是使用基於註釋的系統,而OP則不是。他通過使用逆向工程生成了他的bean和映射。衆所周知,註釋實現與非註釋方式存在一些差異,這也可能導致同一問題的不同原因。 –

+0

你在做什麼像language.getPatients(); – Gokul

+0

@Gokul:不,我沒有 – Barrier

回答

1

你的JSON轉換器嘗試序列整個實體,它包含了所有的病人說每種語言列表。根據我的理解,json中的患者列表並不是預期的。所以你有三個選項(我會考慮它們的順序):

  • 刪除語言實體中患者的映射。你需要從語言實體的患者中獲得 嗎?如果不刪除這個映射。
  • 創建語言DTO,您可以在退出tx圖層之前傳輸數據。這種方式調用服務的人永遠不會得到LazyInitException。毫不奇怪:DTO領域總是熱切期待。
  • 配置您的json轉換器不序列化病人字段。你還沒有說你正在使用哪個json庫。其中一些給你一個註釋來忽略一些字段(例如,傑克遜的@JsonIgnore),其他需要java配置。

要申請第一個解決方案,更新這些文件是這樣的:

Language.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<!-- Generated Sep 14, 2016 4:33:23 PM by Hibernate Tools 4.3.1 --> 
<hibernate-mapping> 
    <class name="beans.Language" table="language" catalog="myglukose" optimistic-lock="version"> 
     <id name="idlanguage" type="java.lang.Integer"> 
      <column name="idlanguage" /> 
      <generator class="identity" /> 
     </id> 
     <property name="language" type="string"> 
      <column name="language" length="45" not-null="true" /> 
     </property> 
    </class> 
</hibernate-mapping> 

Language.java

public class Language implements java.io.Serializable { 
    private Integer idlanguage; 
    private String language; 

    protected Language() { 
    } 


    public Language(String language) { 
     this.language = language; 
    } 

    public Integer getIdlanguage() { 
     return this.idlanguage; 
    } 

    protected void setIdlanguage(Integer idlanguage) { 
     this.idlanguage = idlanguage; 
    } 
    public String getLanguage() { 
     return this.language; 
    } 

    public void setLanguage(String language) { 
     this.language = language; 
    } 
} 

我已經更新了沒有方法到protected。你甚至可以將它們更新到private:只有hibernate應該使用它們(並且它可以使用私有字段/方法)。

+0

謝謝。我是否也應該爲其他桌子做同樣的事情? – Barrier

+1

這個決定應該在個案的基礎上完成:如果你的代碼沒有使用其中一個方面(特別是如果刪除了@(One | Many)ToMany'),我會將雙向關聯改爲單向關聯側)。對於配置表(如語言,國家,偏好等),瞭解所有使用它們的實體並不是一個很大的優勢。另一方面,'@ * ToMany'有許多合法的用途,所以不要試圖將它們全部刪除;) – Thierry

+0

現在我有太多的連接問題,有時候。請看看這個,http://stackoverflow.com/questions/39661594/hibernateexception-too-many-connections-using-c3p0 – Barrier

0

當您嘗試訪問懶場你需要做的休眠的會話關閉之前

從會話的上下文中退出時,如果需要,hibernate無法訪問數據庫,因此會引發LazyInitializationException

javadoc

表示會話環境之外訪問未抓取數據。例如,在會話關閉後訪問未初始化的代理或集合

+0

請檢查更新的問題。另外,如何提供如何實施?我們不必調用save/get等方法,而是需要'Session'服務並完成這項工作?在獲得結果之前,會議沒有關閉。 – Barrier

+0

您好?............... – Barrier

0

從目前的解釋我不能看到你正在做的像:language.getPatients();

但是,如果您正在編寫HQL查詢來訪問所有患者表單語言實體,那麼我認爲您應該使用連接。正如我可以看到異常,如果與beans.Language.patients中的LazyInitializationException相關。

,所以我會建議下面的代碼...檢查是否有用到你或不..

public List<Language> getAllLanguages(Session session) { 
     List<Language> languages=(List<Language>)session.createQuery("from Language as l JOIN l.patients").list(); 
     return languages; 
} 
+0

您使用hbm嗎? – Gokul

+0

我不使用語言來訪問患者。 – Barrier

+0

你能分享你的hbm文件嗎...你的pojo沒有問題 – Gokul

相關問題