I have an entity called Refund, which has two Foreign Keys on the same entity called 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
This class does not have annotations because it has an extend and it is automatically binded by Hibernate, in the hbm.xml. The @ManyToOne works flawlessly and the table is present and has some elements in the Database (which is Oracle).
Inside a JSP, i need to populate a combobox with the elements of this table, filtered by the type column.
As I do here:
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");
    }
}
and, in the 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>
The problem is: for some Refunds (that has absolutely nothing different with "working" ones), the getMotivationsByType() functions gives an exception: object references an unsaved transient instance - save the transient instance before flushing. I tried browsing the Internet and I found this article. After applying the fix, it still gives me an error, but a different exception: ids for this class must be manually assigned before calling save(). Again, tried browsing and found this post, but it suggests to add an auto-increment column Id for the class. This is not what I need, plus, I can not add it.
The strange fact is that if I refresh the JSP on the same "bugged" Refund, it works flawlessly. I tried some fixes which also actually fix the problem, but then I get some regressions on the save, like:
- adding some properties to the foreign key annotations, for example: - updatable=false.. But it doesn't work to me, because the field must be updatable. Putting- updatable=truedoesn't solve the problem.
- removing the - codefrom the- propertyin the combobox path, like so:- <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>
to send the full Entity to the backend, but it does not (entity appears to be null).
- refactoring the combobox syntax, using bean:defineinstead ofc:forEach
- catching the exception and re-launching the same function when caught
- adding the list into the currentPL, this way the list gets retrieved correctly but, after saving or refreshing, it rethrows the same exception.
- setting motivations on nullby default, because maybe since there is not a motivation with anullcode, then Hibernate cannot find a Foreign Key, but nothing.
- adding an auto-generated id column
- separating the two foreign keys in two separated entities
- closing the hibernate session
What is unclear to me is: why does it solve the problem if I change a completely separated snippet of code? And why does it work on the second round?
 
    