0

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>
Aleksandr Kravets
  • 5,750
  • 7
  • 53
  • 72
  • I would have said that an non-persisted entity has no ID set. You're sure every entry of the set has an ID? – sp00m May 07 '12 at 07:43
  • 1
    I think you should not be using the merge in the resultAux, but in the result class, hibernate should handle the one to many relations. Could you post your mapping configuration also? – Eugenio Cuevas May 07 '12 at 07:46
  • @sp00m: Hibernate isn't my strong side. I have some doubts about what happens when I add entry to a ResultAux set retrieved from Result object. Also a set of Result's is persisted above given code. Maybe it's cascading what makes ResultAux'es to be persistent at a point of this code execution. – Aleksandr Kravets May 07 '12 at 07:57
  • @EugenioCuevas: mappings added. See EDIT. – Aleksandr Kravets May 07 '12 at 08:01

2 Answers2

0

I'm not sure my answer will resolve your problem, but to come back on @EugenioCuevas comment, I would have done something like this to persist your child entities:

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

Hibernate should then manage the relations on its own.

sp00m
  • 47,968
  • 31
  • 142
  • 252
0

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

Ken Chan
  • 84,777
  • 26
  • 143
  • 172
  • As a matter of fact... I turned on SQL-logging in hibernate. And generated SQL-statements for new records are inserts with null as ID. Therefore insertion must be happening before the code in question. What do you think? – Aleksandr Kravets May 07 '12 at 08:52
  • If the INSERT SQL with null ID is issued , then these records are inserted already and of course they have IDs .So , what do you want to determine actually ? Determine the records that is just inserted or determine the records that will be inserted into table ?? – Ken Chan May 07 '12 at 09:10
  • I tried to comment out code persisting ResultAux-es. It works regardless of that. So I was right, it's cascading. As i told sp00m Hibernate is not my strong side. The question is off. Thanks! – Aleksandr Kravets May 07 '12 at 09:46