您的json转换器尝试序列化整个实体,该实体包含使用每种语言的所有患者的列表。据我了解,json中的患者列表是不期望的。因此,您有三种选择(订购时我会考虑它们):
在“语言”实体中删除对患者的映射。您需要从语言实体获得患者的准入吗?如果没有,请删除此映射。创建语言DTO,然后在退出tx层之前在其中传输数据。这样,无论谁调用该服务,都将永远不会收到LazyInitException。毫不奇怪:DTO字段总是设置得很热情。配置您的json转换器以不序列化患者字段。您尚未说明正在使用哪个json库。其中一些为您提供注释,以忽略某些字段(@JsonIgnore例如对于Jackson),其他则需要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 /></id><property name='language' type='string'> <column name='language' length='45' not-null='true' /></property> </class></hibernate-mapping>
语言.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创建一个REST API。我创建了一种获取表中所有项目的方法。
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.1import 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,String diabetesOther,String lastName,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; }}
重要提示:Bean和映射是通过NetBeans从MySQL数据库反向工程的。patient调用时,不需要获取任何与之相关的数据getAllLangauges。我的language表格只有2列,idlanguage而language。Patient表的前键为languagetable
在rest api中使用此方法之前,它没有任何异常即可完美运行。但是,当我在rest 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':
对这个问题有什么想法吗?
更新资料
我的配置文件
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 /></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 /></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 /></id><many-to-one name='diabetesType' fetch='select'> <column name='diabetes_type_iddiabetes_type' not-null='true' /></many-to-one><many-to-one name='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 /></set><set name='reminders' table='reminder' inverse='true' lazy='true' fetch='select'> <key><column name='patient_idpatient' not-null='true' /> </key> <one-to-many /></set> </class></hibernate-mapping>