-->
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.  [ 2 posts ] 
Author Message
 Post subject: session.merge() generates unnecessary updates.
PostPosted: Thu Jan 26, 2006 9:46 am 
Newbie

Joined: Wed Oct 05, 2005 3:36 am
Posts: 15
Hibernate version: 3.1.1

Mapping documents: See Below

Code between sessionFactory.openSession() and session.close(): session.merge(a);

Name and version of the database you are using: Postgres 8.0.3

The generated SQL (show_sql=true): See Below

I am attempting to use the session.merge() functionality in order to synchronize the state of the data coming from the web tier with the database, however I am seeing unnecessary updates (when nothing has changed), therefore I am trying to track down the cause.

In order to track down the problem I created a test case with four tables and four classes (A,B,C and D)

Where:
A is the parent of B.
B is the parent of C.
C is the parent of D.

And there are no other relationships present.

All these relationships are bi-directional with the one-to-many side marked as inverse="true" and cascade="all-delete-orphan".
The merge() is working fine (the data gets updated correctly) except that when there is no change to the data it still runs updates on A,B and C however strangely not on D.


I am including the code and hibernate mapping for B as it is representative of the code for all the other classes.

Does anyone have any idea how to stop these phantom updates from occurring?

TIA.
David


PS If I change the initialization of the bags from "new ArrayList()" to "new PersistentBag()" the extra updates go away, however it doesn't save changes correctly.



Code:

package com.mycompany.dal.transfer.impl;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.mycompany.dal.transfer.interfaces.ADTO;
import com.mycompany.dal.transfer.interfaces.BDTO;
import com.mycompany.dal.transfer.interfaces.CDTO;
import org.apache.commons.collections.Closure;
import org.apache.commons.collections.CollectionUtils;

public class BDTOImpl implements BDTO {

    public BDTOImpl () {
    }



    private Long bId;
   
    public Long getBId() {
        return bId;
    }

    public void setBId(Long bId) {
        this.bId = bId;
    }

    private Long concurrentVersion;
   
    public Long getConcurrentVersion() {
        return concurrentVersion;
    }

    public void setConcurrentVersion(Long concurrentVersion) {
        this.concurrentVersion = concurrentVersion;
    }

    // Package level protection so that overrides can access it.
    boolean deleting = false;



    private String name;

    /**
     * Returns the Name.
     *
     * @return String - The Name
     */
    public String getName() {
        return name;
    }

    /**
     * Set the Name.
     *
     * @param name String - The Name.
     */
    public void setName(String name) {
        this.name = name;
    }



    private ADTO a;

    /**
     * Returns the A.
     *
     * @return ADTO - The A.
     */
    public ADTO getA() {
        return a;
    }
   
    public ADTO getAInternal() {
        return a;
    }

    /**
     * Updates the A.
     *
     * @param a - ADTO The A.
     */
    public void setA(ADTO a) {
        if (this.a == a) {
            return;
        }

        if (this.a != null) {
            ((ADTOImpl) this.a).removeBInternal(this);
        }

        this.a = a;

        if (a != null) {
            ((ADTOImpl) a).addBInternal(this);
        }
    }

    public void setAInternal(ADTO a) {
        if (deleting) {
            return;
        }
        if (this.a != a &&
            this.a != null && a != null) {
            throw new IllegalStateException("BDTO cannot be a member of two A collections: " + toString());
        }

        this.a = a;
    }



    private List cs;
    private List csMutable;
    { setCsMutable(new ArrayList()); }

    public List getCsMutable() {
        return csMutable;
    }

    public void setCsMutable(List cs) {
        this.cs = Collections.unmodifiableList(cs);
        this.csMutable = cs;
    }

    public List getCs() {
        return cs;
    }
   
    public void addC(CDTO c) {
        csMutable.add(c);
        ((CDTOImpl) c).setBInternal(this);
    }

    public void addCInternal(CDTO c) {
        csMutable.add(c);
    }
   
    public void removeC(CDTO c) {
        csMutable.remove(c);
        ((CDTOImpl) c).setBInternal(null);
    }

    public void removeCInternal(CDTO c) {
        if (!deleting) {
            csMutable.remove(c);
        }
    }

    public void beforeDelete() {
        // Guard to prevent infinite loop.
        if (deleting) {
            return;
        }
       
        deleting = true;

        if (this.a != null) {
            ((ADTOImpl) this.a).removeBInternal(this);
        }
        CollectionUtils.forAllDo(new ArrayList(csMutable), new Closure() {
            public void execute(Object ob) {
                ((CDTOImpl) ob).beforeDelete();
            }
        });
    }

    public int hashCode() {
        return (new HashCodeBuilder(17,37)
            .append(getBId())
            ).toHashCode();
    }

    public boolean equals(Object o) {
        boolean equals = false;

        if (o != null && o instanceof BDTO) {
            BDTO other = (BDTO) o;

            return (new EqualsBuilder()
                .append(getBId(), other.getBId())
                ).isEquals();
        }

        return equals;
    }
   
    public String toString() {
        return new ToStringBuilder(this)
            .append("bId", getBId())
            .append("name", getName())
            .toString();
    }
}


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 package="com.mycompany.dal.transfer.impl" auto-import="true">
    <class name="com.mycompany.dal.transfer.impl.BDTOImpl" table="b">
        <id name="BId" type="long">
            <column name="b_id" not-null="true"/>
            <generator class="native"/>
        </id>

        <version name="concurrentVersion" column="concurrent_version" type="long"/>

        <property name="Name" type="string">
            <column name="name" length="60" not-null="false"/>
        </property>

        <many-to-one name="AInternal" class="com.mycompany.dal.transfer.impl.ADTOImpl">
            <column name="a_id" not-null="true"/>
        </many-to-one>

        <bag name="CsMutable" cascade="all-delete-orphan" inverse="true">
            <key>
                <column name="b_id" not-null="true"/>
            </key>
            <one-to-many class="com.mycompany.dal.transfer.impl.CDTOImpl"/>
        </bag>

    </class>
</hibernate-mapping>


Code:
05:35:39,887 INFO  [STDOUT] Hibernate: select adtoimpl0_.a_id as a1_162_2_, adtoimpl0_.concurrent_version as concurrent2_162_2_, adtoimpl0_.name as name162_2_, bsmutable1_.a_id as a4_4_, bsmutable1_.b_id as b1_4_, bsmutable1_.b_id as b1_164_0_, bsmutable1_.concurrent_version as concurrent2_164_0_, bsmutable1_.name as name164_0_, bsmutable1_.a_id as a4_164_0_, csmutable2_.b_id as b4_5_, csmutable2_.c_id as c1_5_, csmutable2_.c_id as c1_165_1_, csmutable2_.concurrent_version as concurrent2_165_1_, csmutable2_.name as name165_1_, csmutable2_.b_id as b4_165_1_ from a adtoimpl0_ left outer join b bsmutable1_ on adtoimpl0_.a_id=bsmutable1_.a_id left outer join c csmutable2_ on bsmutable1_.b_id=csmutable2_.b_id where adtoimpl0_.a_id=?
05:35:39,992 INFO  [STDOUT] Hibernate: select ddtoimpl0_.d_id as d1_168_0_, ddtoimpl0_.concurrent_version as concurrent2_168_0_, ddtoimpl0_.name as name168_0_, ddtoimpl0_.c_id as c4_168_0_ from d ddtoimpl0_ where ddtoimpl0_.d_id=?
05:35:40,007 INFO  [STDOUT] Hibernate: select dsmutable0_.c_id as c4_1_, dsmutable0_.d_id as d1_1_, dsmutable0_.d_id as d1_168_0_, dsmutable0_.concurrent_version as concurrent2_168_0_, dsmutable0_.name as name168_0_, dsmutable0_.c_id as c4_168_0_ from d dsmutable0_ where dsmutable0_.c_id=?

*** Start Extra Updates **
05:35:40,030 INFO  [STDOUT] Hibernate: update b set concurrent_version=?, name=?, a_id=? where b_id=? and concurrent_version=?
05:35:40,038 INFO  [STDOUT] Hibernate: update c set concurrent_version=?, name=?, b_id=? where c_id=? and concurrent_version=?
05:35:40,044 INFO  [STDOUT] Hibernate: update a set concurrent_version=?, name=? where a_id=? and concurrent_version=?
*** End Extra Updates **



Code:
            DataAccessLayer dal = DataAccessLayerBuilder.getInstance();
           
            ADAO aDAO = dal.getADAO();
            BDAO bDAO = dal.getBDAO();
            CDAO cDAO = dal.getCDAO();
            DDAO dDAO = dal.getDDAO();
           
            ADTO a = aDAO.newA();
            a.setAId(new Long(1));
            a.setConcurrentVersion(new Long(0));
            a.setName("A");
                       
            BDTO b = bDAO.newB();
            CDTO c = cDAO.newC();
            DDTO d = dDAO.newD();

            b.setBId(new Long(2));
            c.setCId(new Long(3));
            d.setDId(new Long(4));

            b.setConcurrentVersion(new Long(0));
            c.setConcurrentVersion(new Long(0));
            d.setConcurrentVersion(new Long(0));

            b.setName("B");
            c.setName("C");
            d.setName("D");

            b.setA(a);
            c.setB(b);
            d.setC(c);
 
            aDAO.mergeA(a);


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 12, 2006 5:07 am 
Newbie

Joined: Tue Sep 12, 2006 4:54 am
Posts: 2
See http://opensource.atlassian.com/project ... e/HHH-1401 and related issues for the reason that this happened.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.