我使用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.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; } }
重要提示:Bean和映射是通过NetBeans从MySQL数据库反向工程的。patient调用时,不需要获取任何与之相关的数据getAllLangauges。我的language表格只有2列,idlanguage而language。Patient表的前键为language table
patient
getAllLangauges
language
idlanguage
Patient
language table
在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":{"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>
您的json转换器尝试序列化整个实体,该实体包含使用每种语言的所有患者的列表。据我了解,json中的患者列表是不期望的。因此,您有三种选择(订购时我会考虑它们):
@JsonIgnore
要应用第一个解决方案,请按以下方式更新这些文件:
<?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>
语言.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状态才能使用它们(并且它可以使用私有字段/方法)。
setId
protected
private