These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: onFlushDirty produce only updates, no inserts?
PostPosted: Wed Nov 01, 2006 6:27 am 
Regular
Regular

Joined: Fri Nov 07, 2003 6:31 am
Posts: 104
Location: Beijing, China
Hi all,

I suddenly have a problem with my hibernate object interceptor. I use it to create what we call 'Synchro' information such as last_update_date, last_access_date, and so on... on objects load or update.

For instance, entity Adherent originally had no synchro info. Each time an Adherent object is loaded, we create a new Adherent_Synchro record in a separate table.

This is done at the interceptor level:

Code:
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        log.trace("CALLED load(" + entity + "," + id + ")");
        //A Syncrhonizable instance might not yet have an associated instrance of SynchroData.
        //In this case it must be created on first load from the system
        if (entity instanceof Synchronizable) {
            int i = types.length - 1;
            while ((i >= 0) && !propertyNames[i].equals("synchroData")) {
                i--;
            }
            if (i > -1) {
                Timestamp current = new Timestamp(new Date().getTime());
                SynchroData sd = (SynchroData) state[i];
                if (sd.getLastAccessLocal() != null) {
                    ((SynchroData) state[i]).setLastAccessLocal(current);
                } else {
                    state[i] = new SynchroData(current, current, new Timestamp(0), new Timestamp(0));
                }
                return true;
            } else
                throw new HibernateException("The object " + entity.getClass().getCanonicalName() + " should not be tagged 'Synchronizable': it has no 'SynchroData' attribute.");
        }
        return false;
    }

public boolean onFlushDirty(Object entity,
                                Serializable id,
                                Object[] currentState,
                                Object[] previousState,
                                String[] propertyNames,
                                Type[] types) {
        boolean isModified = false;
        log.trace("FLUSHED ENTITY IS: " + entity.getClass().getCanonicalName());
       
        //if the entity is Synchronizable it must possess a SynchroData attribute (named synchroData) whom lastUpdateLocal date value must be updated.
        //Even if the Synchronizable object has not SynchroData yet, the onLoad method should provide it with one.
        //The SynchroData info should have been created at this stage.
        if (entity instanceof Synchronizable) {
            int i = types.length - 1;
            while ((i >= 0) && !propertyNames[i].equals("synchroData")) {
                i--;
            }
            if (i > -1) {
                ((SynchroData) currentState[i]).setLastUpdateLocal(new Timestamp(new Date().getTime()));
                isModified = true;
            } else
                throw new HibernateException("The object " + entity.getClass().getCanonicalName() + " should not be tagged 'Synchronizable': it has no 'SynchroData' attribute.");
        }
        return isModified;
    }


This code used to work fine. I have a lot of Adherent_Synchro records.

Now, the problem is that Hibernate never issues INSERT queries anymore. Only UPDATES, even when there's no related Adherent_Synchro, which the DB doesn't really complain about (just say 0 row updated).

Could dynamic-update="true" dynamic-insert="true" have any impact? I remember having added those rather recently?

Any idea very welcome!

FYI, here what is issued when modifying ADHERENT_ETAT_ACTIVATION property on an Adherent that has no synchro info. It issues an update query on an object which does not exist
Code:
Hibernate: /* update org.xx.common.model.adherent.Adherent */ update ADHERENT set ADHERENT_DATE_MAJ=?, ADHERENT_DATE_SUPPRESSION=?, ADHERENT_ETAT_ACTIVATION=? where ADHERENT_ID=?
Hibernate: /* update org.xx.common.model.adherent.Adherent */ update ADHERENT_SYNCHRO set LAST_ACCESS_LOCAL=?, LAST_UPDATE_LOCAL=?, LAST_ACCESS_REMOTE=?, LAST_UPDATE_REMOTE=? where ADHERENT_SYNCHRO_ADHERENT_ID_FK=?



Hibernate version:3.2.0

Mapping documents:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="org.xx.common.model.adherent.Adherent" table="ADHERENT" dynamic-update="true" dynamic-insert="true">
        <meta attribute="extends" inherit="false">org.xx.common.persistence.BusinessObject</meta>
        <cache usage="read-write"/>

        <id column="ADHERENT_ID" name="id" type="java.lang.Long">
            <generator class="identity"/>
        </id>

        //many properties here

        <join table="ADHERENT_SYNCHRO" fetch="join" optional="true">
            <key column="ADHERENT_SYNCHRO_ADHERENT_ID_FK" on-delete="noaction"/>
            <property name="synchroData" type="org.xx.common.model.synchro.SynchroDataType">
                <column name="LAST_ACCESS_LOCAL" not-null="true"/>
                <column name="LAST_UPDATE_LOCAL" not-null="true"/>
                <column name="LAST_ACCESS_REMOTE" not-null="true"/>
                <column name="LAST_UPDATE_REMOTE" not-null="true"/>
            </property>
        </join>

    </class>
</hibernate-mapping>



Name and version of the database you are using:MSSQL 2000
Code:

_________________
/nodje


Last edited by nodje on Tue Jun 03, 2008 4:54 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 01, 2006 5:33 pm 
Beginner
Beginner

Joined: Mon Dec 06, 2004 4:20 pm
Posts: 34
We do a very similar thing. You need to implement the onSave method - that will get you newly inserted objects, if I am reading your email correctly.

Don


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 02, 2006 4:18 am 
Regular
Regular

Joined: Fri Nov 07, 2003 6:31 am
Posts: 104
Location: Beijing, China
onSave method is implemented of course: which means, on creation of an ADHERENT object, onSave method will create and ADHERENT_SYNCHRO object. This works perfectly.

The problem is, on ADHERENT object update, an ADHERENT_SYNCHRO entity is created. Hibernate interpret this entity as existing already and perform an UPDATE query on a non existing object, instead of an INSERT.

_________________
/nodje


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.