我正在使用JPA(Hibernate),当我尝试从数据库中获取对象时遇到问题。我正在使用Glassfish 3.1.2,Hibernate和Oracle数据库10.2.0.4。
以下是我的应用程序的概念:
答案是表格的答案。表单属于某个类别。用户可以创建表单。用户可以回答。
所以:
如果我试图得到答案,我会收到一个错误(见帖子的底部),但奇怪的是:
如果数据库中没有答案;它起作用(至少没有抛出错误)
如果数据库中存在answer.form_id列中没有任何值的答案;它起作用(至少没有抛出错误)
如果我删除了form属性并让answer属性来自answer类;有用!答案来自数据库并且也有一个用户获取。
如果我从answer类中删除user属性并让form属性;它失败!答案不是来自数据库。 (在这篇文章末尾抛出错误)
如果我从表单类中删除了类别和用户属性;有用!答案来自数据库,并有一个用户和一个表格取得!但我不能这样,我需要在表单实体中有一个类别和一个用户。
如果我删除了category属性或者任何一个user属性,并让另一个属性在表单类中;它失败了。
似乎hibernate不能比其他一个实体获取更多:
但是我在persistence.xml中设置了<property name="hibernate.max_fetch_depth" value="3"/>
。
任何有关问题的想法或建议?它似乎是表单实体的属性类别或用户。
由于
这是我的实际代码,为了清晰起见,大大减少了。
表格类:
@Entity
@Table(name="FORM")
public class Form implements Serializable {
private static final long serialVersionUID = -2101681231828548611L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "G_FORM")
@SequenceGenerator(name = "G_FORM", sequenceName = "FORM_ID_SEQ")
@Column(name = "ID", unique = true, nullable = false)
private int id;
private String name;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn
private Category category;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn
private User user;
//more fields and usual getters and setters
}
用户类:
@Entity
@Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = -821421797110076396L;
@Id
@Column(name = "ID")
private String id;
@NotNull
@Column
private String email;
@NotNull
private String password;
@Column(name="PARENT_ID")
private User parent;
//more fields and usual getters and setters
}
答案课:
@Entity
public class Answer implements Serializable {
private static final long serialVersionUID = -8514559401482729639L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "G_ANSWER")
@SequenceGenerator(name = "G_ANSWER", sequenceName = "ANSWER_ID_SEQ")
@Column(name = "ID", unique = true, nullable = false)
private int id;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn
private Form form;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn
private User user;
//more fields and usual getters and setters
}
失败的AnswerDAO方法:
public List<Answer> getAllAnswers() throws Exception{
TypedQuery<Answer> query = em.createQuery( "SELECT a FROM Answer a ORDER BY a.id", Answer.class );
return query.getResultList();
//return em.createQuery("SELECT a FROM Answer a", Answer.class).getResultList();
}
在我的persistence.xml中:
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.max_fetch_depth" value="3"/>
hibernate生成的sql(看起来是否正确?):
Infos: Hibernate: select answer0_.ID as ID1_0_, answer0_.ANSWER_XML as ANSWER2_0_, answer0_.DATE_UPLOAD as DATE3_0_, answer0_.form_ID as form4_0_, answer0_.user_ID as user5_0_ from Answer answer0_ order by answer0_.ID
Infos: Hibernate: select form0_.ID as ID1_2_2_, form0_.category_NAME as category6_2_2_, form0_.DATE_UPLOAD as DATE2_2_2_, form0_.extention as extentio3_2_2_, form0_.name as name4_2_2_, form0_.QUESTION_XML as QUESTION5_2_2_, form0_.user_ID as user7_2_2_, category1_.NAME as NAME1_1_0_, category1_.DATE_CREATION as DATE2_1_0_, user2_.ID as ID1_5_1_, user2_.ANSWER_COUNT as ANSWER2_5_1_, user2_.DATE_INSCRIPTION as DATE3_5_1_, user2_.DATE_LAST_ANSWER as DATE4_5_1_, user2_.DATE_LAST_LOGIN as DATE5_5_1_, user2_.email as email6_5_1_, user2_.firstname as firstnam7_5_1_, user2_.FORM_COUNT as FORM8_5_1_, user2_.lastname as lastname9_5_1_, user2_.PARENT_ID as PARENT10_5_1_, user2_.password as passwor11_5_1_ from FORM form0_ left outer join Category category1_ on form0_.category_NAME=category1_.NAME left outer join USERS user2_ on form0_.user_ID=user2_.ID where form0_.ID=?
eclipse控制台中的错误也大大减少了:
WARN: SQL Error: 17027, SQLState: null
ERROR: Le flux de données est déjà fermé
Infos: HHH000327: Error performing load command : org.hibernate.exception.GenericJDBCException: could not load an entity: [be.adehis.bean.Form#96]
Avertissement: EJB5184:A system exception occurred during an invocation on EJB AnswerDAO, method: public java.util.List be.adehis.database.dao.AnswerDAO.getAllAnswers() throws java.lang.Exception
Avertissement: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at ...
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not load an entity: [be.adehis.bean.Form#96]
at ...
Caused by: org.hibernate.exception.GenericJDBCException: could not load an entity: [be.adehis.bean.Form#96]
at ...
Caused by: java.sql.SQLException: Le flux de données est déjà fermé
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:113)
Avertissement: EJB5184:A system exception occurred during an invocation on EJB AnswerService, method: public java.util.List be.adehis.service.answer.AnswerService.getAllAnswers() throws java.lang.Exception
Avertissement: javax.ejb.EJBTransactionRolledbackException
at ...
Caused by: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at ...
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not load an entity: [be.adehis.bean.Form#96]
at ...
Caused by: org.hibernate.exception.GenericJDBCException: could not load an entity: [be.adehis.bean.Form#96]
at ...
Caused by: java.sql.SQLException: Le flux de données est déjà fermé
答案 0 :(得分:1)
我发现了问题:
通过JDBC查询Oracle时,是否正在查询表 包含Long或Long Raw数据,可能出现以下错误消息 抛出:
java.sql.SQLException:Stream已经关闭
表单有一个属性questionXml,其中包含以xml格式化的问题。答案有一个属性answerXml,其中包含以xml格式化的答案。两者都保存在数据库中LONG
。 (我的错或休眠错,我不是)
我将列的类型更改为VARCHAR2(255CHAR)
,现在它正在运行!
对我来说奇怪的是,hibernate能够获取Answer&gt;表格或表格&gt;用户但没有回答&gt;表格&gt;用户。
无论如何将LONG更改为VARCHAR2并且它正在运行。
答案 1 :(得分:0)
可能你可以在Many - One上尝试@NotFound(action = NotFoundAction.IGNORE)并查看是否能解决问题。我没有尝试过但有时损坏的数据可能会产生问题。
答案 2 :(得分:0)
我不是Hibernate的专家,但看起来你的数据库连接在查询完成之前就已关闭了:
Le flux de données est déjà fermé => The data stream is already closed.
¿任何其他可能关闭它的线程?或者,由于泄漏检测,您的服务器可能在不幸的时候回收它们。请查看this,看看调整those settings是否能让您朝着正确的方向前进。