Hibernate抛出异常,但只在第一次执行时抛出



我有一个名为Refund的实体,它在同一个名为Motivation的实体上有两个外键。

Refund.java

// other columns
@ManyToOne(targetEntity=Motivation.class, optional=true, fetch=FetchType.LAZY)
@JoinColumn(name="opening_motivation", referencedColumnName="code")
@ForeignKey(name="REFUND_OPENING_MOTIVATION_FK")
private Motivation openingMotivation;
@ManyToOne(targetEntity=Motivation.class, optional=true, fetch=FetchType.LAZY)
@JoinColumn(name="closure_motivation", referencedColumnName="code")
@ForeignKey(name="REFUND_CLOSURE_MOTIVATION_FK")
private Motivation closureMotivation;
// getters and setters

Motivation.java

private String code;
private String type;
private String description;
// getters and setters

这个类没有注释,因为它有一个扩展,并且它是由Hibernate自动绑定的,在hbm.xml@ManyToOne工作完美,表存在,并且在数据库(Oracle)中有一些元素。

在JSP中,我需要用这个表的元素填充一个组合框,通过type列进行筛选。

就像我在这里做的:

MotivationDAO.java

public static List<Motivation> getMotivationsByType(String type) throws DatabaseException  {

Criteria criteria = null;

try {
Session session = HibernateUtil.currentSession();

criteria = session.createCriteria(Motivation.class);
criteria.add(Restrictions.eq("type", type);
return (List<Motivation>) criteria.list(); // the exception I specified later is thrown here

} catch (HibernateException e) {
throw new DatabaseException(e.getMessage());
}catch (Exception e) {
System.out.println("getMotivationList: " + e.getMessage());
throw new DatabaseException("an error occured");
}
}

,在JSP中:

<form:select cssClass="comboBox" path="pageAction.currentPL.entity.openingMotivation.code" id="openingCombo" disabled="true">
<form:option value=""></form:option>
<c:forEach var="openingMotivation" items='<%=MotivationDAO.getMotivationsByType("A")%>'>            
<form:option value="${openingMotivation.code}">${openingMotivation.code} - ${openingMotivation.description}</form:option>
</c:forEach>
</form:select>
问题是:对于一些退款(这与"工作"没有任何区别)。getMotivationsByType()函数给出了一个例外:object references an unsaved transient instance - save the transient instance before flushing。我试着浏览互联网,找到了这篇文章。应用修复后,它仍然给我一个错误,但一个不同的异常:ids for this class must be manually assigned before calling save()。再次,尝试浏览并找到这篇文章,但它建议为类添加一个自动增量列Id。这不是我需要的,而且,我不能添加它。

奇怪的是,如果我在相同的"bug"上刷新JSP;退款,它工作完美无瑕。我尝试了一些修复,实际上也解决了这个问题,但后来我得到一些回归保存,如:

  1. 为外键注释添加一些属性,例如:updatable=false..但是它对我不起作用,因为字段必须是可更新的。把updatable=true放上去并不能解决问题。

  2. code从combobox路径中的property中移除,如下所示:

    <form:select cssClass="comboBox" path="pageAction.currentPL.entity.openingMotivation" id="openingCombo" disabled="true">
    <form:option value=""></form:option>
    <c:forEach var="openingMotivation" items='<%=MotivationDAO.getMotivationsByType("A")%>'>            
    <form:option value="${openingMotivation}">${openingMotivation.code} - ${openingMotivation.description}</form:option>
    </c:forEach>
    </form:select>
    

发送完整的实体到后端,但它没有(实体看起来为空)。

  1. 重构组合框语法,使用bean:define代替c:forEach
  2. 捕获异常并在捕获时重新启动相同的函数
  3. 将列表添加到currentPL中,这样可以正确检索列表,但是在保存或刷新后,它会重新抛出相同的异常。
  4. 默认设置null上的动机,因为可能因为没有null代码的动机,那么Hibernate找不到外键,但什么也找不到。
  5. 添加自动生成的id列
  6. 分隔两个独立实体中的两个外键
  7. 关闭hibernate会话

我不清楚的是:如果我改变一个完全分离的代码片段,为什么它能解决问题?为什么它在第二轮中有效?

这不是一个合适的解决方案,但我发现问题是由会话和线程引起的。在这个项目中,使用内部方法使用线程检索Hibernate当前会话。通过更改线程号,将在下一个使用此当前会话的实例中抛出异常。所以,如果你有同样的问题,试着调查这些事情。

最新更新