Hibernate-懒得初始化一个角色集合:beans.Language.patients,无法初始化代理 – 没有Session

我用hibernate来创建一个rest api。 我创建了一个方法来获取表中的所有项目。

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

这是我的Language.java

 public class Language implements java.io.Serializable { private Integer idlanguage; private String language; private Set patients = new HashSet(0); public Language() { } public Language(String language) { this.language = language; } public Language(String language, Set 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 getPatients() { return this.patients; } public void setPatients(Set 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 illnesses = new HashSet(0); private Set reminders = new HashSet(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 illnesses, Set 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 getIllnesses() { return this.illnesses; } public void setIllnesses(Set illnesses) { this.illnesses = illnesses; } public Set getReminders() { return this.reminders; } public void setReminders(Set reminders) { this.reminders = reminders; } } 

重要提示:bean和映射是通过NetBeans从MySQL数据库进行逆向工程的。 在调用getAllLangauges时,我不需要获取与patient相关的任何数据。 我的language表只有2列, idlanguagelanguage Patient表具有language table

在rest api中使用这个方法之前,它完美无缺。 但是当我在restapi中使用它时,它在那里创造了一个复杂性。

我这里没有使用注释。 我使用了hibernate逆向工程向导来映射上面的实体。 这是我的restapi方法。

 @Path("/language") public class LanguageJSONService { @GET @Path("/getAllLanguages") @Produces(MediaType.APPLICATION_JSON) public List getAllLanguages(){ LanguageService languageService=new LanguageService(); List list = languageService.getAllLanguages(); return list; } } 

这就是我调用方法的方式,

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

     true org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/***** ***** 5 20 3000 50 300 true SELECT 1 ************        

Language.hbm.xml

                     

这是我的患者映射文件,

Patient.hbm.xml

                                       Stores the basic information of the patient                 

您的json转换器尝试序列化整个实体,其中包含说出每种语言的所有患者的列表。 根据我的理解,json中的病人名单是不可预期的。 所以你有三个选项(我会考虑它们的顺序):

  • 删除语言实体中患者的映射。 您是否需要从语言实体获取患者的访问权限? 如果不删除此映射。
  • 创建一个语言DTO,在退出tx图层之前传输数据。 这样,任何调用该服务的人都将永远不会获得LazyInitException。 毫不奇怪:DTO领域总是热切期待。
  • 将json转换器配置为不序列化患者字段。 你没有说过你正在使用哪种json lib。 其中一些给你一个注释来忽略一些字段(例如@JsonIgnore for Jackson),其他需要java配置。

要应用第一个解决方案,请以这种方式更新这些文件:

Language.hbm.xml

               

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; } } 

我已将no-arg构造函数和setId方法更新为protected 。 你甚至可以将它们更新为private :只有hibernate应该使用它们(它可以使用私有字段/方法)。

当您尝试访问惰性字段时,您需要在关闭hibernate会话之前执行此操作。

当您退出会话的上下文时,如果需要,hibernate无法访问数据库,因此抛出了LazyInitializationException

来自javadoc :

表示访问会话上下文之外的未获取数据 。 例如,在会话关闭后访问未初始化的代理或集合时。

根据目前的解释,我无法看到你这样做:language.getPatients();

但是,如果您正在编写HQL查询以访问语言实体的所有患者,那么我认为您应该使用join。 因为我可以看到与beans.Language.patients中的LazyInitializationException相关的exception。

所以我会建议下面的代码…检查它是否对你有用..

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