I started a
topic a while back and I've narrowed the problem.
If you resave an in-memory object, Hibernate will UPDATE every associated Set/Map element even though they haven't changed.
If I load the object from Hibernate (replacing my in-memory version), then this extraneous UPDATE problem doesn't occur.
This seems like a bug, different saving behavior depending on whether it's the original object or one retrieved from the DB. But maybe it's by design and there's something I can do to clue in Hibernate to avoid this?
The work around is to always reload the object from the DB right after you create it for the first time, but that's something of a pain in my design as where I save objects has no idea if the object is new or old.
Thoughts?
Hibernate version:
2.1.6
Mapping documents:
<class name="com.ncube.nable.platform.contentstorage.Volume">
<id name="id" column="ID">
<generator class="native" />
</id>
<map name="files" table="FILES" lazy="false" cascade="all-delete-orphan" >
<key column="VOLUME_ID"></key>
<index column="FILE_NAME" type="text" />
<one-to-many class="com.ncube.nable.platform.contentstorage.cmdinfo.CSSFileInfo" />
</map>
</class>
<class name="com.ncube.nable.platform.contentstorage.cmdinfo.CSSFileInfo">
<id name="id" column="ID">
<generator class="native" />
</id>
<property name="path" />
<property name="size" />
<property name="permissions" />
<property name="lastModifiedTime" />
</class>
Code between sessionFactory.openSession() and session.close():
Volume v = new Volume( "volName", "/volPath" );
CSSFileInfo fileA = new CSSFileInfo( "a", "b", "c", "d" );
CSSFileInfo fileB = new CSSFileInfo( "e", "f", "g", "h" );
v.getFiles().put( fileA.getPath(), fileA );
v.getFiles().put( fileB.getPath(), fileB );
_hibSvc.beginTransaction();
_hibSvc.getSession().saveOrUpdate( v );
_hibSvc.commitTransaction();
_hibSvc.endSession();
System.out.println( "Resaving in-memory Volume" );
_hibSvc.beginTransaction();
_hibSvc.getSession().saveOrUpdate( v );
_hibSvc.commitTransaction();
_hibSvc.endSession();
System.out.println( "Resaving retrieved Volume" );
_hibSvc.beginTransaction();
Volume vLoad = (Volume)_hibSvc.getSession().load( Volume.class, v.getId() );
_hibSvc.getSession().saveOrUpdate( vLoad );
_hibSvc.commitTransaction();
_hibSvc.endSession();
Name and version of the database you are using:
HSQL 1.8.0 and also Oracle 10.
The generated SQL (show_sql=true):
09:47:24,905 [main] DEBUG SchemaExport:149 - create table MC.VS_VOLUMES (
CSS_ID bigint not null,
VOLUME_ID bigint not null,
primary key (CSS_ID, VOLUME_ID)
)
09:47:24,905 [main] DEBUG SchemaExport:149 - create table MC.ContentStorageServer (
ID bigint generated by default as identity (start with 1)
)
09:47:24,905 [main] DEBUG SchemaExport:149 - create table MC.Volume (
ID bigint generated by default as identity (start with 1)
)
09:47:24,905 [main] DEBUG SchemaExport:149 - create table MC.CSSFileInfo (
ID bigint generated by default as identity (start with 1),
path varchar(255),
size varchar(255),
permissions varchar(255),
lastModifiedTime varchar(255),
VOLUME_ID bigint,
FILE_NAME longvarchar
)
09:47:24,905 [main] DEBUG SchemaExport:149 - alter table MC.VS_VOLUMES add constraint FKFFE92CF7273D8460 foreign key (VOLUME_ID) references MC.Volume
09:47:24,905 [main] DEBUG SchemaExport:149 - alter table MC.VS_VOLUMES add constraint FKFFE92CF7770D78F7 foreign key (CSS_ID) references MC.ContentStorageServer
09:47:24,905 [main] DEBUG SchemaExport:149 - alter table MC.CSSFileInfo add constraint FK15D8874D273D8460 foreign key (VOLUME_ID) references MC.Volume
09:47:24,921 [main] INFO SchemaExport:160 - schema export complete
09:47:25,030 [main] DEBUG SQL:226 - insert into MC.Volume (ID) values (null)
09:47:25,061 [main] DEBUG SQL:226 - call identity()
09:47:25,077 [main] DEBUG SQL:226 - insert into MC.CSSFileInfo (path, size, permissions, lastModifiedTime, ID) values (?, ?, ?, ?, null)
09:47:25,077 [main] DEBUG SQL:226 - call identity()
09:47:25,077 [main] DEBUG SQL:226 - insert into MC.CSSFileInfo (path, size, permissions, lastModifiedTime, ID) values (?, ?, ?, ?, null)
09:47:25,093 [main] DEBUG SQL:226 - call identity()
09:47:25,093 [main] DEBUG SQL:226 - update MC.CSSFileInfo set VOLUME_ID=?, FILE_NAME=? where ID=?
09:47:25,108 [main] DEBUG SQL:226 - update MC.CSSFileInfo set VOLUME_ID=?, FILE_NAME=? where ID=?
Resaving in-memory Volume
09:47:25,108 [main] DEBUG SQL:226 - update MC.CSSFileInfo set path=?, size=?, permissions=?, lastModifiedTime=? where ID=?
09:47:25,108 [main] DEBUG SQL:226 - update MC.CSSFileInfo set path=?, size=?, permissions=?, lastModifiedTime=? where ID=?
Resaving retrieved Volume
09:47:25,124 [main] DEBUG SQL:226 - select volume0_.ID as ID0_ from MC.Volume volume0_ where volume0_.ID=?
09:47:25,155 [main] DEBUG SQL:226 - select files0_.VOLUME_ID as VOLUME_ID__, files0_.ID as ID__, files0_.FILE_NAME as FILE_NAME__, files0_.ID as ID0_, files0_.path as path0_, files0_.size as size0_, files0_.permissions as permissi4_0_, files0_.lastModifiedTime as lastModi5_0_ from MC.CSSFileInfo files0_ where files0_.VOLUME_ID=?