-->
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.  [ 5 posts ] 
Author Message
 Post subject: Map with primitive values not persisted.
PostPosted: Fri Apr 15, 2005 3:28 pm 
Regular
Regular

Joined: Fri Feb 13, 2004 10:02 pm
Posts: 90
Read the rules before posting!
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version:
3.0 release
Mapping documents:
Code:
<hibernate-mapping package="com.llic.calc.label">
  <class name="Label" table="Label">
 
    <id name="id" column="labelid" type="java.lang.Long">
      <generator class="native" />
    </id>
       
    <property name="name" column="name" type="string"/>
   
   <many-to-one name="equation" class="com.llic.calc.variable.EquationVariable" lazy="false"/>
   
   <!-- map of database labels -->
   <map name="dbVar" lazy="false">
      <key column="labelid"/>
      <map-key type="java.lang.Long" column="dbvarid"/>
      <element type="java.lang.Long" column="rowId"/>
   </map>
   
  </class>
</hibernate-mapping>



Name and version of the database you are using:
MySQL 4.0

I am trying to persist a map, the value could potentially be null. When the value is null, I am not getting any rows persisted in the database. If the value is not null, a record is inserted. Is this the expected behavior? I need the key to signal that an object was visited, but if the value of the map is null, then the traversed object did not have a value when it was visited. Therfore, when I load these objects I need to null to signal a special case. Is there any way around to get the row to insert with the null value short of a usertype?


Top
 Profile  
 
 Post subject: Re: Map with primitive values not persisted.
PostPosted: Mon Apr 18, 2005 2:18 am 
Newbie

Joined: Mon Sep 13, 2004 6:02 pm
Posts: 12
Location: Seattle, WA
tnine wrote:
I am trying to persist a map, the value could potentially be null. When the value is null, I am not getting any rows persisted in the database. If the value is not null, a record is inserted. Is this the expected behavior? I need the key to signal that an object was visited, but if the value of the map is null, then the traversed object did not have a value when it was visited. Therfore, when I load these objects I need to null to signal a special case. Is there any way around to get the row to insert with the null value short of a usertype?


As far as I've investigated, this by design, though I'm not sure the justification. The PersistentMap class in Hibernate3 (and the Map class in Hibernate2) treat null values the same as if the key were never set. In fact, if you load a PersistentMap, then set an existing key's value to null, Hibernate will delete that entry.

There's a bug in this code such that if a null value happens to make it into the persisted map (such as through another, non-Hibernate-enabled client), and Hibernate loads that Map, and you try to overwrite the entry with a non-null value, you can end up with a unique constraint violation, as Hibernate will incorrectly treat the new value as an insert, rather than an update. I've attached a patches for both Hib2 and Hib3 to fix the issue (trivial change---just use containsKey, rather than a null check). Unfortunately, Gavin doesn't see this as a bug, and is "not inclined to fix it." Again, I'm not sure the justification, as Gavin doesn't explain. But he has turned the bug into a low-priority improvement request, which means it will likely be awhile before it gets looked at again.

Personally, I don't understand why PersistentMap must treat null values the same as if they weren't even in the Map. As you've clearly pointed out, tnine, there's a clear semantic difference between having a null value and not being in the map. Maybe this is answered in the docs somewhere, but it would seem that PersistentMap is imposing an artificial limitation where one isn't necessary.

Currently, the only way around this, as far as I know, is to create your own version of PersistentMap that is null-friendly. Unfortunately, there's no plugin mechanism that would allow you to replace this at runtime, so you'd have to patch your own version of Hibernate.

Or you could file a bug on this. Maybe with enough people asking for it, Gavin will be "inclined to fix it."


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 18, 2005 7:56 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Some databases does not allow a PK to have 1 null column

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 18, 2005 9:35 am 
Regular
Regular

Joined: Fri Feb 13, 2004 10:02 pm
Posts: 90
Emmanuel,
Thanks for the reply. I can understand the behavior if it were one of the composite key columns that were null, but it is not. In the dbvar table there are 3 columns (labelid, dbvarid, rowid). The primary key is a compsite key of the labelid and the dbvarid. In the scenario I gave before, The map does have a key, but the value is null. Therefore the properties to satisfy the composite key are present, but the value (rowid) would just be null. Below is an example of how I am using the map.

Code:
dbVar.put(new Long(1), new Long(10); // gets persisted
dbVar.put(new Long(2), null); //does not get persisted.


As you can see from above, there is a key in the map, just a null value. Shouldn't the rowid column simply contain null?

Todd


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 18, 2005 9:56 am 
Regular
Regular

Joined: Fri Feb 13, 2004 10:02 pm
Posts: 90
Shaug and Emmanual,
After reviewing your posts, and the jira bug. I can understand Gavin's view on not persisting a null value. If you read the javadoc on the put(Obj key, Obj value) of the Map interface, it does not state that the implementation must accept Null values. Some implementations, such as the Hashtable implementation, throw a NullPointerException when the value is null. Although the Hibernate implentation conforms to the interface specification and is therefore technically correct, it does not meet the needs of developers who need to persist null values. Is it possible to add a boolean attribute to the map tag to specify that null values can be persisted? This allows the PersistentMap implementation to still conform to the interface spec, and allows developers like Shaug and I to be able to persist null values.

Todd


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