-->
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: mutable="false" calls strange updates when deletin
PostPosted: Sun Aug 19, 2007 8:06 pm 
Newbie

Joined: Sat Jul 28, 2007 7:24 am
Posts: 8
Hibernate version: 3.2.4 sp.1

Mapping documents:
Code:
<hibernate-mapping default-access="field" package="hb.test">
    <class name="Category" table="CATEGORY" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="ID" type="long">
            <generator class="native" />
        </id>
        <property name="name" column="NAME" type="string" />
        <bag name="books" cascade="save-update, delete, delete-orphan" inverse="true">
            <key column="CATEGORY_ID" />
            <one-to-many class="Book" />
        </bag>
    </class>
</hibernate-mapping>

<hibernate-mapping default-access="field" package="hb.test">
    <class name="Book" table="BOOK" dynamic-insert="true" dynamic-update="true" mutable="false">
        <id name="id" column="ID" type="long">
            <generator class="native" />
        </id>
        <property name="title" type="string" length="50">
            <column name="TITLE" sql-type="char(50)" />
        </property>
        <many-to-one name="category" class="Category" column="CATEGORY_ID" foreign-key="BOOK_CATEGORY_FK"
            not-null="true" />
        <list name="chapters" cascade="save-update, delete, delete-orphan">
            <key column="BOOK_ID" foreign-key="CHAPTER_BOOK_FK" not-null="true" />
            <list-index column="_INDEX" base="1" />
            <one-to-many class="Chapter" />
        </list>
    </class>
</hibernate-mapping>

<hibernate-mapping default-access="field" package="hb.test">
    <class name="Chapter" table="CHAPTER" dynamic-insert="true" mutable="false">
        <id name="id" column="ID" type="long">
            <generator class="native" />
        </id>
        <property name="title" type="string" length="50">
            <column name="TITLE" length="50" sql-type="char(50)" />
        </property>
        <many-to-one name="book" class="Book" column="BOOK_ID" insert="false" update="false" />
    </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
save:
Code:
Transaction tx = session.beginTransaction();
Category category = new Category("super");
Book book = new Book("Forrest Gump");
Chapter chapter = new Chapter("Winston Groom");
book.addChapter(chapter);
category.addBook(book);
session.save(category);
tx.commit();


delete:
Code:
Transaction tx = session.beginTransaction();
Category c = (Category) session.createQuery("from Category c where c.id = 1").list().get(0);
System.out.println("About to execute delete: " + c);
session.delete(c);
tx.commit();


Name and version of the database you are using:
MySQL 5.0.41 for Win32

The generated SQL (show_sql=true):
This is the log generated by Hibernate when the delete code is executed:
Code:
Hibernate:
    /*
from
    Category c
where
    c.id = 1 */ select
        category0_.ID as ID0_,
        category0_.NAME as NAME0_
    from
        test.CATEGORY category0_
    where
        category0_.ID=1
00:50:56,9265p LongType:172 - returning '1' as column: ID0_
00:50:56,9465p StringType:172 - returning 'super' as column: NAME0_
About to execute delete: [Category: super]
Hibernate:
    /* load one-to-many hb.test.Category.books */ select
        books0_.CATEGORY_ID as CATEGORY3_1_,
        books0_.ID as ID1_,
        books0_.ID as ID1_0_,
        books0_.TITLE as TITLE1_0_,
        books0_.CATEGORY_ID as CATEGORY3_1_0_
    from
        test.BOOK books0_
    where
        books0_.CATEGORY_ID=?
00:50:56,9665p LongType:133 - binding '1' to parameter: 1
00:50:56,9765p LongType:172 - returning '1' as column: ID1_0_
00:50:56,9765p StringType:172 - returning 'Forrest Gump' as column: TITLE1_0_
00:50:56,9765p LongType:172 - returning '1' as column: CATEGORY3_1_0_
00:50:56,9765p LongType:172 - returning '1' as column: CATEGORY3_1_
00:50:56,9765p LongType:172 - returning '1' as column: ID1_
Hibernate:
    /* load one-to-many hb.test.Book.chapters */ select
        chapters0_.BOOK_ID as BOOK3_1_,
        chapters0_.ID as ID1_,
        chapters0_._INDEX as column4_1_,
        chapters0_.ID as ID2_0_,
        chapters0_.TITLE as TITLE2_0_,
        chapters0_.BOOK_ID as BOOK3_2_0_
    from
        test.CHAPTER chapters0_
    where
        chapters0_.BOOK_ID=?
00:50:56,9865p LongType:133 - binding '1' to parameter: 1
00:50:57,0065p LongType:172 - returning '1' as column: ID2_0_
00:50:57,0065p StringType:172 - returning 'Winston Groom' as column: TITLE2_0_
00:50:57,0165p LongType:172 - returning '1' as column: BOOK3_2_0_
00:50:57,0165p LongType:172 - returning '1' as column: BOOK3_1_
00:50:57,0165p LongType:172 - returning '1' as column: ID1_
00:50:57,0165p IntegerType:172 - returning '1' as column: column4_1_
Hibernate:
    /* update
        hb.test.Book */ update
            test.BOOK
        set
            TITLE=?,
            CATEGORY_ID=?
        where
            ID=?
00:50:57,0365p StringType:133 - binding 'Forrest Gump' to parameter: 1
00:50:57,0365p LongType:133 - binding '1' to parameter: 2
00:50:57,0365p LongType:133 - binding '1' to parameter: 3
Hibernate:
    /* update
        hb.test.Chapter */ update
            test.CHAPTER
        set
            TITLE=?
        where
            ID=?
00:50:57,0465p StringType:133 - binding 'Winston Groom' to parameter: 1
00:50:57,0465p LongType:133 - binding '1' to parameter: 2
Hibernate:
    /* delete hb.test.Chapter */ delete
        from
            test.CHAPTER
        where
            ID=?
00:50:57,0465p LongType:133 - binding '1' to parameter: 1
Hibernate:
    /* delete hb.test.Book */ delete
        from
            test.BOOK
        where
            ID=?
00:50:57,0865p LongType:133 - binding '1' to parameter: 1
Hibernate:
    /* delete hb.test.Category */ delete
        from
            test.CATEGORY
        where
            ID=?
00:50:57,0965p LongType:133 - binding '1' to parameter: 1
00:50:57,2165p SessionFactoryImpl:769 - closing


And the question is: why when I delete an object, the selects have to be invoked (is this because Hibernate loads the collection proxies and so on so as to cascade the deletion?)
And why are these two update statements executed? They don't seem to make much sense since I don't change anything, and apart from that the mappings for Book and Chapter say these are immutable classes, and according to the tutorial, no updates should ever be done on such classes. That's going on - did I do something wrong?
Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 20, 2007 10:25 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
Looks like the updates are a bug.

There's a ditryCheck method in DefaultFlushEntityEventListener which comes to the conclusion that its impossible to dirty check the immutable object so defaults to updating it just in case.

This is because of an "optimisation" for immutable objects causing their loadedState (EntityEntry) to be discarded.

In EntityEntry it does this:
public void setStatus(Status status) {
if (status==Status.READ_ONLY) {
loadedState = null; //memory optimization
}
this.status = status;
}

Then in DefaultFlushEntityEventListener.dirtyCheck it says this:
cannotDirtyCheck = loadedState==null; // object loaded by update()

As you can ses, there's a difference in understanding of what loadedState = null means.

I removed the optimisation and rebuilt hibernate - the updates go away.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 20, 2007 10:40 am 
Newbie

Joined: Sat Jul 28, 2007 7:24 am
Posts: 8
So if this is a bug, maybe this should be reported somewhere? Anyway, thanks.


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.