2013-05-15 76 views
1

我正在使用JPA(休眠),當我嘗試從我的數據庫中獲取對象時遇到問題。我使用的是Glassfish 3.1.2,Hibernate和Oracle數據庫10.2.0.4。JPA休眠 - @ManyToOne得不到正確

這裏是我的應用程序的概念:

答案是一個窗體的答案。表單屬於一個類別。用戶可以創建表單。用戶可以回答。

所以:

  • 1窗體有一個類別,所以1類可能有幾種形式
  • 1回答有1種形式,1種形式可能有幾個答案
  • 1回答有1個用戶(答案作者)
  • 1形式具有1個用戶(形式的創造者)

如果我試圖讓我得到一個錯誤的答案(見職位的底部)b ut奇怪的事實是:

  • 如果數據庫中沒有答案;它起作用(至少沒有錯誤拋出)

  • 如果答案在answer.form_id列中沒有任何值的數據庫中存在;它工作(至少沒有錯誤拋出)

  • 如果我刪除表單屬性,並讓答案類的用戶屬性;有用!答案是從數據庫中獲取,也有一個用戶獲取。

  • 如果我從答案類中刪除用戶屬性並讓表單屬性;它失敗!答案不是從數據庫中獲得的。 (在本文結尾處拋出錯誤)

  • 如果我從類刪除類別和用戶屬性;有用!答案是從數據庫獲得,並有一個用戶和表單獲取!但我不能讓它這樣,我需要在表單實體中有一個類別和一個用戶。

  • 如果我刪除了任何一個category屬性或兩個用戶屬性,並讓另一個在窗體類中;它失敗。

看來,Hibernate無法進一步獲取比一個其他實體:

  • 解答>用戶:OK
  • 解答>的形式沒有類別或用戶:OK
  • 形式>類別:OK
  • form>用戶:好的
  • 答案> form> category:FAIL
  • 答案> form> user:失敗

但是我在我的persistence.xml中設置了<property name="hibernate.max_fetch_depth" value="3"/>

有什麼想法或建議是什麼問題?它似乎是表單實體或其屬性類別或用戶。

感謝


這裏是我實際的代碼,嚴重降低了清晰度。

Form類:

@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é 

回答

1

我發現這個問題:

This article說:

When querying Oracle via JDBC, if a table that is being queried contains Long or Long Raw data, the following error message may be thrown:

java.sql.SQLException: Stream has already been closed

的形式有一個屬性questionXml包含XML格式的問題。答案有一個屬性answerXml,其中包含用xml格式化的答案。兩者均以LONG保存在DB中。 (我的故障或休眠故障,我沒有)

我改變了列的類型爲VARCHAR2(255CHAR),它現在工作!

對我來說奇怪的是,hibernate能夠獲取Answer> Form或Form> User但不是Answer> Form> User。

無論如何改變LONG到VARCHAR2,它的工作。

0

也許你可以在Many-One上試試@NotFound(action = NotFoundAction.IGNORE),看看是否解決了這些問題。我還沒有嘗試過,但有時損壞的數據可能會產生問題。

+0

我把'@NotFound(action = NotFoundAction。IGNORE)'在用戶和形式attriburtes在答案類和用戶和類別在表單類:同樣的錯誤:'( – Jon

0

我在Hibernate中沒有專家,但它看起來像你的數據庫連接被關閉查詢完成之前:

Le flux de données est déjà fermé => The data stream is already closed.

¿可能被關閉任何其他線程?或者,也許你的服務器由於泄漏檢測而在不幸的時間收回它們。看看this,看看是否調整those settings讓你走向正確的方向。

+0

是的,我同意連接看起來被關閉,但我在開發階段,我'我沒有發現任何可以訪問數據庫的線程,也沒有其他的SQL查詢在控制檯中記錄下來,我會看看你的鏈接,並會回覆關於這個 – Jon

+0

的任何消息由於你的第二個鏈接,我這樣做了:'asadmin set resources.jdbc-connection-pool.pool-name.statement-leak-timeout-in-seconds = 300'和'asadmin set resources.jdbc-connection-pool.pool -name.statement-leak-reclaim = true'但它仍然會拋出相同的錯誤: WARN:SQL錯誤:17027,SQLState:null 錯誤:Le flux dedonnéesestdéjàfermé'和相同的堆棧跟蹤。:( – Jon