Search code examples
javahibernateone-to-manyhibernate-onetomany

Hibernate: new or old record


I have a OneToMany connection between tables Result and ResultAux. I can retrieve a set of ResultAux objects from Result. After that I'm adding some ResultAux objects to set and using merge on each set entry to flush changes into database. Like this:

Set<ResultAux> resultAuxes = result.getResultAuxes();
if (resultAuxes != null) {
    for (ResultAux resultAux : resultAuxes) {
        resultAux = getDaoFactory().getResultAuxDAO().merge(resultAux);
    }
}

For some additional actions i need to know is set entry a new record and will be inserted into table or it's an old one and (modified or not) will be updated. I noticed that all entries of ResultAux set already have an ID, so i can't check it for null as i did for other tables. Is there any way to determine such thing (prefferably not involving extra libs)?

EDIT:

<hibernate-mapping>
    <class name="ResultAux" table="RESULT_AUX">
        <id name="id" column="ID">
            <generator class="native" />
        </id>

        <property name="additinalInfoType" column="AITYPE" type="dao.hibernate.utl.AdditinalInfoEnumType" />
        <property name="sorter" column="SORTER" />
        <property name="value1" column="VAL1" />
        <property name="value2" column="VAL2" />

        <many-to-one name="result" column="RESULT_ID" class="Result" />
    </class>
</hibernate-mapping>

<hibernate-mapping>
    <class name="Result" table="RESULT">
        <id name="id" column="ID">
            <generator class="native" />
        </id>

        <property name="questionNumber" column="Q_NUM" />
        <property name="answerNumber" column="A_NUM" />
        <property name="questionGroup" column="Q_GRP" />
        <property name="answerValue" column="A_VAL" />
        <set name="resultAuxes" inverse="true" cascade="all-delete-orphan"
            lazy="false">
            <key column="RESULT_ID" />
            <one-to-many class="ResultAux" />
        </set>
    </class>
</hibernate-mapping>

Solution

  • Using native as the the primary key generation strategy causes Hibernate to select identity, sequence or hilo as the PK generation strategy depending upon the capabilities of the underlying DB.

    I think for your DB , hibernate selects "sequence" strategy such that you may experience this problem (Records that are not inserted to the DB can have the assigned ID) by the following codes:

    Set<ResultAux> resultAuxes = result.getResultAuxes();
    ResultAux  newResultAux = new ResultAux();
    
    /**
     * As session.save()  requires to return the ID for the saved instance , if  "sequence" strategy is 
     * used , Hibernate will hit the DB  to select the next ID (eg. select some_seq.NEXTVAL) to be used 
     * for the saved instance. So newResultAux  will have an ID after save()  but actually it is not saved to 
     * the DB yet as  saving to the DB  occurs during session.flush()
     */
    session.save(newResultAux);
    resultAuxes.add(newResultAux);
    

    One of the solutions is to add a @Version property to the ResultAux . Then you could check the value of this @Version property to determine whether it is a new record or not as the @Version property for a new record must be NULL