2016-09-22 88 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

相关问题