Search code examples
javaoracle-databasehibernatehibernate-mapping

Problems inserting many-to-one row in Hibernate with Oracle


I am having a problem inserting a parent and associated children records into an Oracle 11g database using Hibernate 4.3.5. I have a Record class that contains a set of Image objects.

Record class mapping:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wts.service.model.Record" table="RECORDS">
        <id name="recordId" type="long">
            <column name="REC_ID" precision="10" scale="0"/>
            <generator class="sequence"><param name="sequence">RECORDS_SEQ</param></generator>
        </id>
        ...
        <set name="images" inverse="true" cascade="all">
            <key column="IMG_REC_ID"/>
            <one-to-many class="com.wts.service.model.Image"/>
        </set>
    </class>
</hibernate-mapping>

Image class mapping:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wts.service.model.Image" table="IMAGES">
        <id name="imageId" type="long">
            <column name="IMG_ID" precision="10" scale="0"/>
            <generator class="sequence"><param name="sequence">IMAGES_SEQ</param></generator>
        </id>
        <many-to-one name="record" column="IMG_REC_ID" not-null="true"/>
    </class>
</hibernate-mapping>

When I call session.save() on the record, I get the following error:

 java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("IMAGES"."IMG_REC_ID")

I followed the bidirectional one-to-many hibernate association guide and many different variations, but I could never get Hibernate to insert Record's primary key into the Image's foreign key column! This is a very simple association (and common use case), so I must be doing something a little bit off here. Does anyone have any idea what I am doing wrong here??

EDIT:

I have also tried setting the key to not-null, and I get the same error:

<set name="images" inverse="true" cascade="all">
        <key column="IMG_REC_ID" not-null="true"/>
        <one-to-many class="com.wts.service.model.Image"/>
    </set>

Also, as a side note, I am able to get this to work when I don't have inverse="true" set. The following code works (the Record and Image(s) are persisted to the database), but the Images object isn't able to have the many-to-one association set:

<set name="images" inverse="false" cascade="all">
        <key column="IMG_REC_ID" not-null="true"/>
        <one-to-many class="com.wts.service.model.Image"/>
    </set>

EDIT 2:

Here is my code where I am calling session.save(). The images are already associated with the record and are populated via a REST web service POST. The record and the images were not previously persisted.

public void createRecord(Record record) {
        //set the create bys for the images and actions
        record.setCreateDt(new Date());

        for (Image image : record.getImages()) {
            image.setCreateBy(record.getCreateBy());
            image.setCreateDt(record.getCreateDt());
        }
        for (Action action : record.getActions()) {
            action.setCreateBy(record.getCreateBy());
            action.setCreateDt(record.getCreateDt());
        }
        session.save(record);
    }

Here are the sql statements that are run after session.commit():

14:43:06,586 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: select RECORDS_SEQ.nextval from dual
14:43:06,715 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: select IMAGES_SEQ.nextval from dual
14:43:06,847 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: insert into RECORDS (REC_EXT_ID, REC_GRP_ID, REC_APPL, REC_LATITUDE, REC_LONGITUDE, REC_PRIVATE, REC_LOCKED, REC_CREATE_BY, REC_CREATE_DT, REC_UPDATE_BY, REC_UPDATE_DT, REC_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:43:06,969 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: insert into IMAGES (IMG_REC_ID, IMG_STATUS, IMG_CT_CD, IMG_FORMAT, IMG_WIDTH, IMG_HEIGHT, IMG_IMAGE, IMG_CREATE_BY, IMG_CREATE_DT, IMG_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:43:08,090 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-1) SQL Error: 1400, SQLState: 23000
14:43:08,090 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-1) ORA-01400: cannot insert NULL into ("FOSUSER"."IMAGES"."IMG_REC_ID")

Solution

  • It looks like you have added image entity to images collection of the record and not set record to this image entity. Like this:

    Image img = new Image();
    Record rec = new Record();
    rec.getImages().add(img);
    // img.setRecord(rec);    Looks like this is missing in your code
    session.save();
    

    In this case during persistance of the image entity hibernate tries to insert null into non nullable field.

    UPD.

    Please add class attribute to the many-to-one element. And remove not-null="true":

    <many-to-one name="record" column="IMG_REC_ID" class="Record"/>