我有一个名为"退款"的实体,它在名为"动机"的同一个实体上有两个外键。
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
。我试着浏览互联网,找到了this article。应用修复程序后,它仍然给我一个错误,但一个不同的异常:ids for this class must be manually assigned before calling save()
。再次尝试浏览并找到this post,但它建议为类添加一个自动递增的列ID。这不是我所需要的,而且,我不能添加它。
奇怪的是,如果我刷新JSP上相同的"bug"退款,它的工作完美。我尝试了一些修复,实际上也解决了这个问题,但然后我得到一些回退保存,如:
1.将一些属性添加到外键注解中,例如:updatable=false
..但是它对我不起作用,因为字段必须是可更新的。放置updatable=true
不能解决问题。
1.从组合框路径中的property
中删除code
,如下所示:
<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
1.捕获异常并在捕获时重新启动同一函数
1.将列表添加到currentPL
中,这样可以正确检索列表,但是在保存或刷新之后,它会再次抛出相同的异常。
1.默认情况下在null
上设置动机,因为可能由于null
代码没有动机,因此Hibernate无法找到外键,但什么也找不到。
1.添加自动生成的ID列
1.将两个外键分隔为两个单独的实体
1.关闭休眠会话
我不清楚的是:为什么我改变一个完全分离的代码片段就能解决问题?2为什么它在第二轮就能工作?
提前感谢愿意帮忙的人!
1条答案
按热度按时间r8uurelv1#
这不是一个正确的解决方案,但我发现问题是由会话和线程引起的。在这个项目中,使用了一个内部方法来检索使用线程的Hibernate当前会话。通过更改线程号,在使用此当前会话的下一个示例中会抛出异常。因此,如果您遇到相同的问题,请尝试调查这些问题。