繁体   English   中英

JPA休眠-@ManyToOne无法正确获取

[英]JPA Hibernate - @ManyToOne not getting correctly

我正在使用JPA(休眠),尝试从数据库中获取对象时遇到问题。 我正在使用Glassfish 3.1.2,Hibernate和Oracle数据库10.2.0.4。

这是我的应用程序的概念:

答案是表格的答案。 表单属于类别。 用户可以创建表格。 用户可以回答。

所以:

  • 1种形式有一个类别,所以1类可能有几种形式
  • 1个答案有1个形式,一种形式可能有多个答案
  • 1个答案有1个用户(答案作者)
  • 1个表单有1个用户(表单创建者)

如果我尝试获得答案,则会收到错误消息(请参阅文章底部),但奇怪的是:

  • 如果数据库中没有答案; 它有效(至少没有抛出错误)

  • 如果数据库中存在答案,而answer.form_id列中没有任何值; 它有效(至少没有抛出错误)

  • 如果我删除了表单属性,并从答案类中让用户属性; 有用! 答案是从数据库中获取的,并且也有一个用户。

  • 如果我从答案类中删除用户属性并让表单属性离开; 它失败! 答案不是从数据库获得的。 (在此帖子的末尾抛出错误)

  • 如果我从表单类中删除类别和用户属性; 有用! 答案是从数据库获取的,也有用户和表格! 但是我不能这样,我需要在表单实体中有一个类别和一个用户。

  • 如果删除类别属性或用户属性中的任何一个,然后将另一个属性放到表单类中, 它失败。

休眠似乎不能比其他实体获取得更多:

  • 答案>用户:确定
  • 答案>没有类别或用户的表单:确定
  • 表格>类别:确定
  • 表格>用户:确定
  • 答案>表格>类别:失败
  • 答案>表格>用户:FAIL

但是,我在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"/>  

休眠生成的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é

我发现了问题:

这篇文章说:

通过JDBC查询Oracle时,如果要查询的表包含Long或Long Raw数据,则可能会引发以下错误消息:

java.sql.SQLException:流已关闭

该表单具有一个属性questionXml,其中包含以xml格式设置的问题。 答案的属性answerXml包含以xml格式设置的答案。 两者都在数据库中另存为LONG (我的错或冬眠的错,我不是)

我将列的类型更改为VARCHAR2(255CHAR) ,它现在可以工作了!

对我来说奇怪的是,休眠状态能够获取Answer> Form或Form> User,但无法获取Answer> Form> User。

无论如何,将LONG更改为VARCHAR2即可使用。

也许您可以尝试在许多上使用@NotFound(action = NotFoundAction.IGNORE)-看看是否可以解决问题。我没有尝试过,但有时损坏的数据可能会导致问题。

我不是Hibernate的专家,但是看起来您的数据库连接在查询完成之前已关闭:

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

¿其他任何线程可能正在关闭它? 也许是由于泄漏检测,您的服务器在不幸的时间回收了它们。 看看这个 ,看看是否可以通过调整这些设置来朝正确的方向前进。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM