-->
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.  [ 14 posts ] 
Author Message
 Post subject: Enum field stored as an int (Int32) causes unneeded UPDATE
PostPosted: Wed May 23, 2007 4:41 am 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
I'm using NHibernate 1.0.3 to persist an entity with an enum field. This field is a bitmask, which I want to store in the database (SQL 2000) as an int. I defined the mapping type as Int32:

<property name="flags" access="field" column="flags" type="Int32" not-null="true" />

This appeared to work, but then I noticed that NHibernate is updating the entity unnecessarily. After some debugging, I saw that whenever I retrieve the entity, then Flush() it considers it dirty. Int32Type.IsDirty() (inherited from AbstractType) just calls "Equals(old, current)", which returns false when "old" is of the enum type, but "current" is of type Int32, having been just read from the database.

As a workaround I've changed the type of the field in the code to int, but is there a proper way to do this? I cannot find an enum type in NHibernate, except for "EnumStringType", which is not what I want.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 23, 2007 5:07 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
You can just leave out the type in the mapping, NHibernate will detect and use the right type automatically.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 23, 2007 8:32 pm 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
Thanks, that works, but we specify the type everywhere else (I seem to remember that it's recommended for better start-up performance and it's just good to be explicit). I found that I can specify the full assembly-qualified name of the type and that works as well. I have two requests, however:

Firstly, the scenario where Int32 type is specified for an enum should not appear to work - NHibernate should throw an exception on start-up and tell the user what to change ("leave out the type name or specify the full assembly-qualified type name"). The user should not have to debug the NHibernate source code to work out why there is an extra UPDATE happening - if they notice it at all.

Secondly, it would be nice if the short type name worked for the enum, ie. no assembly name if it's in the same assembly as the type being mapped and no namespace if it's in the same namespace, just as you can specify <many-to-many class="RelatedClass"> with no namespace or assembly name.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 24, 2007 3:23 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Quote:
Firstly, the scenario where Int32 type is specified for an enum should not appear to work - NHibernate should throw an exception on start-up and tell the user what to change ("leave out the type name or specify the full assembly-qualified type name").


How is NHibernate supposed to do this while avoiding reflection to determine the actual property type?

The reason the enum type cannot be specified is that it would require inventing special syntax for these types.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 25, 2007 2:36 am 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
Good point - NHibernate would have to do reflection to work out that the type is wrong. Maybe it could do that in some sort of "debug" mode? Alternatively, specifying the type as an "Int32" could be made to work correctly. Int32Type, Int16Type and other types that can act as enum bases could have special checks for this case: if comparison fails the value being compared to is an enum then convert it to a number and try to compare again.

If you're wondering why I'm so persistent about this, seemingly trivial, issue: this problem, in combination with a SQL server problem, has actually caused our database replication to fail in production. So it may seem small, but it's resulted in a lot of trouble.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 25, 2007 3:04 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Something like hbmlint could be useful here, but I don't think adding hacks into integer types is the right thing to do.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 25, 2007 3:13 am 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
Well, then perhaps it could use reflection on start-up after all, just to check for this case? It probably wouldn't slow things down noticeably, considering it's already compiling things with CodeDom, etc. Of course it would need to be profiled to tell for sure. Again, the reflection check would only be needed for numeric types.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 25, 2007 3:45 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
If you don't specify any type attribute, NHibernate will do the right thing automatically. Since you specified the type attribute, it's your responsibility to ensure that the type was specified correctly. In this case it wasn't.

Yes, a tool could be created to check for this, but I currently have no time to work on it. Contributions are welcome.

Besides, using reflection to determine the type of a single property is not such a costly operation. Unless, of course, you have lots of enum properties in all your classes.


Top
 Profile  
 
 Post subject:
PostPosted: Sun May 27, 2007 12:18 am 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
Yes, obviously I did the wrong thing by specifying Int32 as the type of the property, but the problem is that it appeared to work. It's also a fairly easy mistake to make (IMO) and I'd be surprised if I was the only one that ran into it.

So if I contributed a patch that performed a reflection check when reading the configuration (ie. not in a separate tool), would that be accepted?


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 29, 2007 10:15 pm 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
Bump. I'm happy to supply a patch for this, but I don't want to work on it if it wouldn't actually get accepted.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 30, 2007 1:38 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I can't tell exactly without looking at the actual patch, but I most probably wouldn't accept it if it was done the way you describe.

If a separate tool was created instead, even though the tool would check just for this one problem at first, I would accept it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 30, 2007 3:23 am 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
You said earlier that using Reflection to check the type wouldn't be too costly, so what's wrong with the approach I described?

The problem with a separate tool is that nobody would run it - especially if it just checked for this one problem.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 30, 2007 4:13 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
That's not what I said. I said that if you leave out the type of the enum property and let NHibernate find it out using reflection, it's not going to slow you down much.

On the other hand, checking that the programmer specified the type of every property correctly in the XML file defeats the whole point of specifying the type explicitly to avoid reflection.

Of course a tool checking for just one problem would not be useful, but it could be used as the platform to which more checks could be added in the future. Hibernate Tools has a similar tool for Hibernate called hbmlint.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 30, 2007 11:43 pm 
Beginner
Beginner

Joined: Sun Apr 09, 2006 9:07 pm
Posts: 24
OK, I understand the reasoning now. I'm not going to start a new tool, but if one is created I think this check should be added to it and I might be able to contribute a patch for it then.


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