-->
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.  [ 8 posts ] 
Author Message
 Post subject: Extra sql calls?
PostPosted: Sun Dec 24, 2006 12:31 am 
Newbie

Joined: Sun Dec 24, 2006 12:10 am
Posts: 3
Hi,

I'm new to Hibernate and have a basic question. I create a new object, call some setter methods and save it in the session using session.saveOrUpdate(entity). After that, I don't commit the session immediately but continue modifying values for entity.
eg:
entity.setEmployeeNumber(399);
entity.setEmployeeType("Supervisor");

session.saveOrUpdate(entity);

entity.setEmployeeNumber(599);
entity.setEmployeeType("New Worker");

session.saveOrUpdate(entity);
transaction.commit();

I notice at commit time, hibernate calls 2 sql calls:

Hibernate: insert into owner.test_table (EMPLOYEE_TYPE, EMPLOYEE_NUMBER, ID) values (?, ?, ?)
Hibernate: update owner.test_table set EMPLOYEE_TYPE=?, EMPLOYEE_NUMBER=? where ID=?

Ideally I think it should have made only a single insert call at commit time. Please let me know if I'm missing something or this is truly an optimization issue.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 24, 2006 8:08 am 
Expert
Expert

Joined: Tue Dec 28, 2004 7:02 am
Posts: 573
Location: Toulouse, France
Please use the code tags to make your code more readable.

First, you should know that's it's not necessary to call session.save() many times on an object. Once is sufficient.

Second, to be sure answering your question, it'd be useful to see your mappings and that you explain what are your objects and their relationships.

But the problem you're describing seems to be a quite usual problem. Did you map a <set> or at least a collection between your two entities. Then just add inverse="true" as an attribute to <set> (or the other collection mapping you're using).

It should do the trick.

_________________
Baptiste
PS : please don't forget to give credits below if you found this answer useful :)


Last edited by batmat on Sun Dec 24, 2006 1:35 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 24, 2006 11:30 am 
Newbie

Joined: Sun Dec 24, 2006 12:10 am
Posts: 3
Thanks. My purpose is to simply play with Hibernate to see what its doing and how its doing and not to apply best practices as yet. I specially want to compare Hibernate with TopLink where usually once the object is registered with unit of work, the application plays around with the object clone.

As far as the table, this is a stand alone table with no relationships (I started really simple !). I have only one POJO entity called TestEntity (with no relationships) called TestEntity and here is its mapping:

<hibernate-mapping>
<class name="com.test.hibernateTest.TestEntity" table="schema.test_table">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="employeeType" type="string" column="EMPLOYEE_TYPE"/>
<property name="employeeNumber" type="integer" column="EMPLOYEE_NUMBER"/>
</class>
</hibernate-mapping>

Here is the hibernate configuration:

<hibernate-configuration>

<session-factory>
<property name="hibernate.connection.driver_class">COM.ibm.db2.jdbc.app.DB2Driver</property>
<property name="hibernate.connection.url">jdbc:db2:TESTDB</property>
<property name="hibernate.connection.username">dd</property>
<property name="hibernate.connection.password">dd</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="show_sql">true</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
<property name="hibernate.hbm2ddl.auto">update</property>

<mapping resource="com/test/hibernateTest/TestEntity.hbm.xml"/>
</session-factory>

</hibernate-configuration>

As you can see its really simple with no relationships. Would appreciate your help.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 24, 2006 1:55 pm 
Expert
Expert

Joined: Tue Dec 28, 2004 7:02 am
Posts: 573
Location: Toulouse, France
If you're doing only simple things to try out, don't activate second level cache. Put org.hibernate.cache.NoCacheProvider instead of HashtableCacheProvider you put.

Do not use saveOrUpdate(). It's a particular method for particular use-case (See http://www.hibernate.org/hib_docs/v3/re ... veorupdate for more informations on this).

I don't see why it generates an insert, then an update. It shouldn't. Try and see if calling save() on your persistent object instead of saveOrUpdate() changes something, although it shouldn't in your case since this is the same instance.

Hibernate does not normally do insert() then update(). Maybe in your case it could possibly due to the FlushMode you're using. Are you sure both sql commands are sent at commit? Because one solution I see is that Hibernate is immediately calling "INSERT" at your first saveOrUpdate() statement for some reason (FlushMode.ALWAYS behaves this way for example), and then an update on the second statement.

How do you create your session object?

_________________
Baptiste
PS : please don't forget to give credits below if you found this answer useful :)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 24, 2006 4:57 pm 
Senior
Senior

Joined: Sat Nov 27, 2004 4:13 am
Posts: 137
hi, try to change first saveOrUpdate to save, and then omit the second one, the problem must be solved.

Another question, how are your primary keys are generated? Because on insert a primary key must be generated, and from that line of code on the entity will contain a valid primary key...

_________________
don't forget to credit!

Amir Pashazadeh
Payeshgaran MT
پايشگران مديريت طرح
http://www.payeshgaran.co
http://www.payeshgaran.org
http://www.payeshgaran.net


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 30, 2006 1:04 pm 
Newbie

Joined: Sun Dec 24, 2006 12:10 am
Posts: 3
Not to dwell too much on an old topic, but I found the answer to this. According to the "Hibernate in Action" book page 127, the sql INSERT statement contains values at the point save() is called. If at any point after this the object is modified, changes are propogated using ans sql UPDATE. Well this seems to be the behavior inherent in Hibernate though its a little surprising.

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 01, 2007 9:44 am 
Senior
Senior

Joined: Tue Aug 23, 2005 8:52 am
Posts: 181
I think its only batching the SQLs till the flush call is made and there isnt any optimization prior to that.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 02, 2007 10:48 am 
Expert
Expert

Joined: Tue Dec 28, 2004 7:02 am
Posts: 573
Location: Toulouse, France
hussaa wrote:
According to the "Hibernate in Action" book page 127, the sql INSERT statement contains values at the point save() is called. If at any point after this the object is modified, changes are propogated using ans sql UPDATE. Well this seems to be the behavior inherent in Hibernate though its a little surprising.


I just understood why save() has obviously to execute immediately in case of a newly instantiated object. To understand, just look at the save() signature and javadoc:
Code:
   /**
    * Persist the given transient instance, first assigning a generated identifier. (Or
    * using the current value of the identifier property if the <tt>assigned</tt>
    * generator is used.) This operation cascades to associated instances if the
    * association is mapped with <tt>cascade="save-update"</tt>.
    *
    * @param object a transient instance of a persistent class
    * @return the generated identifier
    * @throws HibernateException
    */
   public Serializable save(Object object) throws HibernateException;


Now, it's obvious: the save() method returns the persistent object identifier. So in case of a new object that is mapped to use a db generated id, Hibernate can't return anything without sending the query to the DB to retrieve this generated id (or with generator=identity for example)...

This is certainly one of the main reasons why the persist() method, defined in the JSR-220, is void... Because Hibernate is forced to issue the insert directly when using save(), not with persist().

_________________
Baptiste
PS : please don't forget to give credits below if you found this answer useful :)


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