-->
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.  [ 7 posts ] 
Author Message
 Post subject: records updated even when no changes are made
PostPosted: Thu Sep 22, 2005 5:05 pm 
Newbie

Joined: Tue Jul 05, 2005 12:42 pm
Posts: 5
I am having a problem in that everytime a record is loaded and viewed it gets updated back to the database even if no changes (I think) were made.

Hibernate version:3.0.5

Mapping documents:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping
SYSTEM "/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="org.archiviststoolkit.model.Subjects" table="subjects" lazy="false">
<id name="subjectId" column="SubjectId">
<generator class="increment"/>
</id>

<version name="version" type="java.lang.Long" column="version"/>

<property name="creationdate" type="java.util.Calendar" column="creationdate"/>
<property name="modifieddate" type="java.util.Calendar" column="modifieddate"/>
<property name="createdBy" type="string" column="createdBy"/>
<property name="modifiedBy" type="string" column="modifiedBy"/>

<property name="term" column="term"/>
<property name="termType" column="termType" type="subjectTermType"/>
<property name="termSource" column="termSource"/>
<property name="scopeNote" column="scopeNote"/>
</class>
</hibernate-mapping>



The generated SQL (show_sql=true):
Hibernate: update subjects set version=?, creationdate=?, modifieddate=?, createdBy=?, modifiedBy=?, term=?, termType=?, termSource=?, scopeNote=? where SubjectId=? and version=?
Hibernate: select subjects0_.SubjectId as SubjectId0_, subjects0_.version as version0_0_, subjects0_.creationdate as creation3_0_0_, subjects0_.modifieddate as modified4_0_0_, subjects0_.createdBy as createdBy0_0_, subjects0_.modifiedBy as modifiedBy0_0_, subjects0_.term as term0_0_, subjects0_.termType as termType0_0_, subjects0_.termSource as termSource0_0_, subjects0_.scopeNote as scopeNote0_0_ from subjects subjects0_ where subjects0_.SubjectId=?


Code:
/*
* Subject.java
*
* Created on July 19, 2005, 11:54 AM
*
* To change this template, choose Tools | Options and locate the template under
* the Source Creation and Management node. Right-click the template and choose
* Open. You can then make changes to the template in the Source Editor.
*/

package org.archiviststoolkit.model;

import org.archiviststoolkit.mydomain.DomainObject;
import com.jgoodies.binding.beans.ExtendedPropertyChangeSupport;

import java.beans.PropertyChangeListener;

/**
* @author leemandell
*/
public class Subjects extends DomainObject {

   private Long subjectId;
   private String term = "";
   private SubjectTermType termType = null;
   private String termSource = "";
   private String scopeNote = "";


   private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(this);


   /**
    * Creates a new instance of Subject
    */
   public Subjects() {
   }

   /**
    * @return Returns the identifier.
    */
   public Long getIdentifier() {
      return getSubjectId();
   }

   /**
    * @param identifier The identifier to set.
    */
   public void setIdentifier(Long identifier) {
      this.setSubjectId(identifier);
   }

   public void addPropertyChangeListener(PropertyChangeListener x) {
      changeSupport.addPropertyChangeListener(x);
   }

   public void removePropertyChangeListener(PropertyChangeListener x) {
      changeSupport.removePropertyChangeListener(x);
   }

   public Long getSubjectId() {
      return subjectId;
   }

   public void setSubjectId(Long subjectId) {
      this.subjectId = subjectId;
   }

   public String getTerm() {
      return term;
   }

   public void setTerm(String term) {
      this.term = term;
   }

   public SubjectTermType getTermType() {
      return termType;
   }

   public void setTermType(SubjectTermType termType) {
      this.termType = termType;
   }

   public String getTermSource() {
      return termSource;
   }

   public void setTermSource(String termSource) {
      this.termSource = termSource;
   }

   public String getScopeNote() {
      return scopeNote;
   }

   public void setScopeNote(String scopeNote) {
      this.scopeNote = scopeNote;
   }

}



[code]
package org.archiviststoolkit.mydomain;

//==============================================================================
// Import Declarations
//==============================================================================

import java.util.Calendar;
import java.util.GregorianCalendar;

import org.hibernate.classic.Lifecycle;
import org.hibernate.Session;
import org.archiviststoolkit.ApplicationFrame;

import java.io.Serializable;

import com.jgoodies.binding.beans.Model;


/**
* The DomainObject should be the base class of all data types which
* we wish to store in our hibernate based database.
* TODO: Integer should be a Long identifier within hibernate
*/

public abstract class DomainObject implements Lifecycle, Comparable {


/**
* Hibernate Version tracker.
*/
private Long version = new Long(0);

/**
* When the object was created.
*/
private Calendar creationdate = new GregorianCalendar();

/**
* When the object was last modified.
*/
private Calendar modifieddate = new GregorianCalendar();

private String createdBy = "";
private String modifiedBy = "";

/**
* @return Returns the creationdate.
*/
public final Calendar getCreationdate() {
return creationdate;
}

/**
* @param creationdate The creationdate to set.
*/
public final void setCreationdate(Calendar creationdate) {
this.creationdate = creationdate;
}

/**
* @return Returns the identifier.
*/
public abstract Long getIdentifier();

/**
* @param identifier The identifier to set.
*/
public abstract void setIdentifier(Long identifier);

/**
* @return Returns the modifieddate.
*/
public final Calendar getModifieddate() {
return modifieddate;
}

/**
* @param modifieddate The modifieddate to set.
*/
public final void setModifieddate(Calendar modifieddate) {
this.modifieddate = modifieddate;
}

/**
* @return Returns the version.
*/
public final Long getVersion() {
return version;
}

/**
* @param version The version to set.
*/
public final void setVersion(Long version) {
this.version = version;
}

/**
* Tests objects for equality.
*
* @param object the object to test against
* @return true if the object equals this object
*/

public boolean equals(final Object object) {

if (object == null) {
return (false);
}

if (this == object) {
return true;
}

if (this.getClass() == object.getClass())
{
if (this.getIdentifier() != null && ((DomainObject) object).getIdentifier() != null
&& (this.getIdentifier().equals(((DomainObject) object).getIdentifier())))
{
return true;
}
}

return false;
}

/**
* Returns the hashcode for this object.
*
* @return the hashcode
*/

public int hashCode() {
if (this.getIdentifier() == null) {
return (-1);
}

return (this.getIdentifier().intValue());
}

/**
* Called when an entity is deleted.
*
* @param session the session to delete on
* @return true to veto delete
*/
public final boolean onDelete(final Session session) {
return (false);
}

/**
* Called after an entity is loaded.
*
* @param session the session which loaded the entity
* @param serialid the identifier of the entity
*/

public void onLoad(final Session session, final Serializable serialid) {

}

/**
* Called when an entity is saved.
*
* @param session the session to save on
* @return true to veto save
*/
public final boolean onSave(final Session session) {
GregorianCalendar calendar = new GregorianCalendar();

this.setCreationdate(calendar);
this.setModifieddate(calendar);
this.setCreatedBy(ApplicationFrame.currentUser);
this.setModifiedBy(ApplicationFrame.currentUser);

return (false);
}

/**
* Called when an entity is updated.
*
* @param session the session to update on
* @return true to veto update
*/
public final boolean onUpdate(final Session session) {
GregorianCalendar calendar = new GregorianCalendar();

this.setModifieddate(calendar);
this.setModifiedBy(ApplicationFrame.currentUser);

return (false);

}

/**
* Compares this object to another.
*
* @param object the object to compare this to.
* @return a integer result of the comparison.
*/
public int compareTo(Object object) {
if (this.getClass() != object.getClass()) {
throw (new ClassCastException("Cannot compare unlike objects"));
}

return (toString().compareToIgnoreCase(object.toString()));
}

public String getCreatedBy() {
return createdBy;
}

public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}

public String getModifiedBy() {
return modifiedBy;
}

public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
}
[code][/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 22, 2005 10:10 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Use the Hibernate log to find out which attribute you changed.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 22, 2005 10:32 pm 
Expert
Expert

Joined: Sat Jun 12, 2004 4:49 pm
Posts: 915
or set 'toogle watchpint' on attribute in eclipse debugger


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 23, 2005 10:16 am 
Newbie

Joined: Tue Jul 05, 2005 12:42 pm
Posts: 5
Here is the dump from the logs. I can't see anything that is different and is causing the record to be saved.

10:12:03,230 DEBUG Loader: done entity load
10:12:03,230 DEBUG JDBCContext: after autocommit
10:12:03,230 DEBUG AbstractFlushingEventListener: flushing session
10:12:03,230 DEBUG AbstractFlushingEventListener: processing flush-time cascades
10:12:03,230 DEBUG AbstractFlushingEventListener: dirty checking collections
10:12:03,230 DEBUG AbstractFlushingEventListener: Flushing entities and processing referenced collections
10:12:03,231 DEBUG AbstractFlushingEventListener: Processing unreferenced collections
10:12:03,231 DEBUG AbstractFlushingEventListener: Scheduling collection removes/(re)creates/updates
10:12:03,231 DEBUG AbstractFlushingEventListener: Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
10:12:03,231 DEBUG AbstractFlushingEventListener: Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
10:12:03,231 DEBUG Printer: listing entities:
10:12:03,232 DEBUG Printer: org.archiviststoolkit.model.Users{password=lee, userName=Lee, modifieddate=2005-09-23 09:23:18, modifiedBy=lee, userId=1, institution=Archivists' Toolkit, createdBy=lee, firstName=Lee, creationdate=2005-09-16 16:53:02, lastName=Mandell}
10:12:03,232 DEBUG AbstractFlushingEventListener: executing flush
10:12:03,232 DEBUG AbstractFlushingEventListener: post flush
10:12:03,232 DEBUG SessionImpl: closing session
10:12:03,233 DEBUG ConnectionManager: closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
10:12:03,233 DEBUG DriverManagerConnectionProvider: returning connection to pool, pool size: 1
10:12:03,233 DEBUG JDBCContext: after transaction completion
10:12:03,233 DEBUG SessionImpl: after transaction completion
10:12:05,492 DEBUG SessionImpl: opened session at timestamp: 4618177435611136
10:12:05,492 DEBUG Cascades: id unsaved-value: null
10:12:05,492 DEBUG AbstractSaveEventListener: detached instance of: org.archiviststoolkit.model.Users
10:12:05,492 DEBUG DefaultSaveOrUpdateEventListener: updating detached instance
10:12:05,492 DEBUG DefaultSaveOrUpdateEventListener: updating [org.archiviststoolkit.model.Users#1]
10:12:05,492 DEBUG DefaultSaveOrUpdateEventListener: calling onUpdate()
10:12:05,492 DEBUG DefaultSaveOrUpdateEventListener: updating [org.archiviststoolkit.model.Users#1]
10:12:05,493 DEBUG AbstractFlushingEventListener: flushing session
10:12:05,493 DEBUG AbstractFlushingEventListener: processing flush-time cascades
10:12:05,493 DEBUG AbstractFlushingEventListener: dirty checking collections
10:12:05,493 DEBUG AbstractFlushingEventListener: Flushing entities and processing referenced collections
10:12:05,493 DEBUG DefaultFlushEntityEventListener: Updating entity: [org.archiviststoolkit.model.Users#1]
10:12:05,493 DEBUG AbstractFlushingEventListener: Processing unreferenced collections
10:12:05,493 DEBUG AbstractFlushingEventListener: Scheduling collection removes/(re)creates/updates
10:12:05,493 DEBUG AbstractFlushingEventListener: Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects
10:12:05,493 DEBUG AbstractFlushingEventListener: Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
10:12:05,493 DEBUG Printer: listing entities:
10:12:05,493 DEBUG Printer: org.archiviststoolkit.model.Users{password=lee, userName=Lee, modifieddate=2005-09-23 09:23:18, modifiedBy=lee, userId=1, institution=Archivists' Toolkit, createdBy=lee, firstName=Lee, creationdate=2005-09-16 16:53:02, lastName=Mandell}
10:12:05,493 DEBUG AbstractFlushingEventListener: executing flush
10:12:05,494 DEBUG BasicEntityPersister: Updating entity: [org.archiviststoolkit.model.Users#1]
10:12:05,494 DEBUG AbstractBatcher: about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
10:12:05,494 DEBUG ConnectionManager: opening JDBC connection
10:12:05,494 DEBUG DriverManagerConnectionProvider: total checked-out connections: 0
10:12:05,494 DEBUG DriverManagerConnectionProvider: using pooled JDBC connection, pool size: 0
10:12:05,494 DEBUG SQL: update users set creationdate=?, modifieddate=?, createdBy=?, modifiedBy=?, userName=?, password=?, firstName=?, lastName=?, institution=? where UserId=?
Hibernate: update users set creationdate=?, modifieddate=?, createdBy=?, modifiedBy=?, userName=?, password=?, firstName=?, lastName=?, institution=? where UserId=?
10:12:05,494 DEBUG AbstractBatcher: preparing statement
10:12:05,495 DEBUG BasicEntityPersister: Dehydrating entity: [org.archiviststoolkit.model.Users#1]
10:12:05,495 DEBUG CalendarType: binding '2005-09-16 16:53:02' to parameter: 1
10:12:05,496 DEBUG CalendarType: binding '2005-09-23 09:23:18' to parameter: 2
10:12:05,496 DEBUG StringType: binding 'lee' to parameter: 3
10:12:05,496 DEBUG StringType: binding 'lee' to parameter: 4
10:12:05,497 DEBUG StringType: binding 'Lee' to parameter: 5
10:12:05,497 DEBUG StringType: binding 'lee' to parameter: 6
10:12:05,497 DEBUG StringType: binding 'Lee' to parameter: 7
10:12:05,497 DEBUG StringType: binding 'Mandell' to parameter: 8
10:12:05,498 DEBUG StringType: binding 'Archivists' Toolkit' to parameter: 9
10:12:05,498 DEBUG LongType: binding '1' to parameter: 10
10:12:05,498 DEBUG AbstractBatcher: Adding to batch
10:12:05,498 DEBUG AbstractBatcher: Executing batch size: 1
10:12:05,499 DEBUG AbstractBatcher: about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
10:12:05,499 DEBUG AbstractBatcher: closing statement
10:12:05,499 DEBUG AbstractFlushingEventListener: post flush
10:12:05,500 DEBUG SessionImpl: closing session
10:12:05,500 DEBUG ConnectionManager: closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
10:12:05,500 DEBUG DriverManagerConnectionProvider: returning connection to pool, pool size: 1
10:12:05,500 DEBUG JDBCContext: after transaction completion
10:12:05,500 DEBUG SessionImpl: after transaction completion
10:12:09,045 DEBUG ConnectionManager: running Session.finalize()
10:12:09,045 DEBUG ConnectionManager: running Session.finalize()


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 23, 2005 11:05 am 
Expert
Expert

Joined: Wed Apr 06, 2005 5:03 pm
Posts: 273
Location: Salt Lake City, Utah, USA
Looks like you are closing the session you loaded the object in, opening another one, and calling session.update() (post your session code if this isn't true). I believe that will make Hibernate update the object every time. If the object hasn't changed, you can use session.lock() to re-associate it with the session, instead of session.update().

_________________
nathan


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 23, 2005 2:07 pm 
Newbie

Joined: Tue Jul 05, 2005 12:42 pm
Posts: 5
Yes, I am closing the session that retrieves the object and then using another session for doing the update. My reading of the documentation is that this is a normal pattern and that the dirty checking should determine if the object needs to be saved or not.

I tried using the session.lock() but then no changes get saved even when some are made.

I am not sure I understand the sequencing of things.

I want to load an object by id and display it in a window that allows the user to change data (or not) and then save the record only if there has been a change in the data. I want to use 2 different sessions since there is no way to tell how long the window will be open. What am I missing.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 23, 2005 2:48 pm 
Expert
Expert

Joined: Wed Apr 06, 2005 5:03 pm
Posts: 273
Location: Salt Lake City, Utah, USA
I think that Hibernate can only do dirty detection while the object is persistent. (See http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html#objectstate-overview). If you detach the object, when you call update(), how can Hibernate guarantee that the object matches the persistent record without hitting the db (executing the update)?

If you are worried about the extra update when the object hasn't changed, your UI should detect changes by the user (you should do your own dirty checking), so you know whether to call update() or not.

_________________
nathan


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