Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
hibernate3
I have a association where File and status are 2 different entities and i have a join table called filestatus which contains the fileId and StatusCode.I also have a additional column called lastUpdatedTime Stamp.
The fileId is auto generated on a sequence.
When i recieve a file i should save it in the database by assigning a status code to it.
Here is what i have in the mapping documents
Mapping documents:
File:-
<class name="com.test.MyFile" table="INBOUND_FILE">
<id name="fileId" type="long" column="FILE_ID">
<generator class="sequence">
<param name="sequence">FILE_ID_SEQ</param>
</generator>
</id>
<set name="MyFileStatus" table="FILE_STATUS" inverse="true" cascade="save-update">
<key column="FILE_ID"/>
<one-to-many class="com.test.FileStatus"/>
</set>
</class>
FileStatus:-
<class name="com.test.FileStatus" table="FILE_STATUS" mutable="false">
<composite-id name="id" class="com.test.FileStatus$Id">
<key-property name="fileId" access="field" column="FILE_ID"/>
<key-property name="statusCode" access="field" column="STAT_CD"/>
</composite-id>
<timestamp name="lstUpdatedTime" access="property" source="vm" column="LST_UPDT_DTTM"/>
<many-to-one name="myFile" class="com.test.MyFile" column="FILE_ID" not-null="true" insert="false" update="false"/>
<many-to-one name="status" class="com.test.Status" column="STAT_CD" not-null="true" insert="false" update="false"/>
</class>
Code between sessionFactory.openSession() and session.close():
getHibernateTemplate().save(myFile);
I am using spring to take care of the session
Full stack trace of any exception that occurs:
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:420)
... 5 more
Caused by: java.sql.BatchUpdateException: ORA-02291: integrity constraint (FILE_STATUS_FK2) violated - parent key not found
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10768)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
... 12 more
Database used: Oracle 10G
The generated SQL (show_sql=true):
select FILE_ID_SEQ.nextval from dual
Hibernate: select status_.STAT_CD, status_.STAT_TYPE_CD as STAT2_6_, status_.STAT_DESC as STAT3_6_ from STATUS status_ where status_.STAT_CD=?
Hibernate: insert into MY_FILE (FILE_ID) values (?)
Hibernate: insert into MY_FILE_STATUS (LST_UPDT_DTTM, FILE_ID, STAT_CD) values (?, ?, ?)
Code in the FIleStatus class:
public class FileStatus implements Serializable{
public static class Id implements Serializable {
private long fileId;
private String statusCode;
public Id() {}
public Id(long fileId,String statusCode){
this.fileId = fileId;
this.statusCode = statusCode;
}
}
private Id id = new Id();
private MyFile myFile;
private Status status;
private Date lstUpdatedTime;
public fileStatus() {}
public fileStatus(MyFile myFile, Status status){
// Set the fields
this.myFile = myFile;
this.status = status;
// Set the identifier values
this.id.fileId = myFile.getFileId();
this.id.statusCode = status.getStatusCode();
//Gaurantee referential integrity
myFile.addFileStatus(this);
}
// all other setters and getters required
}
Code used to test this:-
MyFile file = new MyFile();
FileStatus fileStatus = new FileStatus(file,status);
file.addFileStatus(fileStatus);
FileFactory.saveFile(file);
The first thing after i give a call to save is generating me the sequence number to set to the fileID and inserting the File record with the generated Id. However, by looking at the logs i see that the parameter that is binded to the SQL for inserting the file status is '0' (which is the default value assigned when the file object is first created) . after the fileId is generated, i am unable to associate it back to the FileStatus object unless both of them are different calls.
Everything works fine if i first save the File and then add the FileStatus to the FIle and do an update on the File,
Am i missing something or am i doing something wrong?
I took the concept of having the inner class for the composite it from the book Hibernate in Action.
Please help me out.