-->
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: Id generador problem
PostPosted: Thu Jan 24, 2008 1:27 pm 
Regular
Regular

Joined: Mon Oct 02, 2006 12:03 pm
Posts: 62
I've developed an application that uses NHibernate. The problem is that the application is performed 2 times at the same time, so there are 2 instances running at the same time in the same machine under the same user (I'm running the application using 2 Terminal Sessions).

The problem is, when I'm trying to create a Entity in one instance application, for example, an article, the NHibernate generates and Id value, for example 12,

Code:
<class name="Model.Entities.ComplexArticle, Model" table="ARTICLE">
    <id name="Id" column="ID" type="Int32" unsaved-value="-1">
      <generator class="increment"/>
    </id>


If I create an article in the other instance application, the NHibernate generates 13 identificator value, ... But, the problem appears when if, now I use the first application in other to create an other article, the NHibernate, generates 13 identificator value!! So, when I create this last article, I'm inserting an article into database that already exists.

How Can I to solve this problem?
I will appreciate a lot your help.

Code:
NHibernate.ISession session = this.session_factory.OpenSession();
            NHibernate.ITransaction tx = session.BeginTransaction();

Model.Entities.ComplexArticle article = new Model.Entities.ComplexArticle(...);

session.SaveOrUpdate(article);
tx.Commit();

session.close();


Thanks for all in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 24, 2008 2:03 pm 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
Hi,
1. I'd consider this a bug you should report.
2. use a different generation strategy: sequence will work perfectly for oracle. I'd expect most databases to support some safe way to create id's (autoid or sequence). You could use UUIDs or if everything fails you could roll your own: create a table which contains the maximum value used. For each id you need do:
1. lock the table exclusively
2. increment the id using the new value as your id
3. commit (releasing the lock)
Note: the lock is a huge bottleneck for any concurrent application, but it is necessary to prevent what you just described. This is why autoid/sequence is recommended to use.

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 24, 2008 4:27 pm 
Regular
Regular

Joined: Mon Oct 02, 2006 12:03 pm
Posts: 62
I don't believe that it is a bug, I believe that is the behaviour of the increment generator. I thank that increment generator got from database the max value of the table column field (so, SELECT MAX(ID) + 1 FROM TABLE) each time that it is necessary. However, I don't know if it is truth or not.

Thansk for your attention.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 26, 2008 11:49 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
jeusdi wrote:
I don't believe that it is a bug, I believe that is the behaviour of the increment generator. I thank that increment generator got from database the max value of the table column field (so, SELECT MAX(ID) + 1 FROM TABLE) each time that it is necessary. However, I don't know if it is truth or not.

Thansk for your attention.


Well you see the behaviour, so it is the behaviour. But if a library (hibernate) that is intended among others for use in highly parallel use (web applications) offers a mechanism for ID generation that is not safe for parallel use. Then this is a bug according to my standards.

Jens

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 26, 2008 1:23 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Where did you guys get the idea that IncrementGenerator is "safe for parallel use"? Just about any piece of documentation on it says explicitly that it's not. It's only intended for testing.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 27, 2008 6:31 am 
Expert
Expert

Joined: Thu Jul 05, 2007 9:38 am
Posts: 287
<flame mode on>
Where did you guy get the idea that wle have the idea that IncrementGenerator is "safe for parallel use"? Just about any piece of this thread says explicitly that it's not.

And I did a quick check on this claim.
Quote:
Just about any piece of documentation on it says explicitly that it's not. It's only intended for testing.


I personally consider http://www.hibernate.org/hib_docs/reference/en/html/mapping.html an important part of documentation. And it states:

Quote:
generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster.


The first part hints at the problem, but the second part suggests it is only a problem in clusters. So it should really read:

"Do not use it. We will remove it in the next release. It is not save in to use in webapplications, applications that have two or more threads, applications that have two or more sessions, applications that will have ever more then one instance running."

So at my standards, offering an antifeature that is broken, is a bug. It's llike a button in a car that shuts off the breaks. Sure you can put a lable next to it: Only safe to use when not driving. But it will still be a mayor flaw.
<flame mode off>

_________________
Please rate useful posts.


Schauderhaft: Softwaredevelopment, Projectmanagement, Qualitymanagement and all things "schauderhaft"


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 27, 2008 3:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Documentation says:
Quote:
generates identifiers of any integral type that are unique only when no other process is inserting data into the same table. Do not use in a cluster.

It can probably be more clear; on the other hand, I would think it is obvious that second instance of the same application is another process.

In any case, here is how the IncrementGenerator works: The generator is created and kept with the SessionFactory. On the first request to get the next ID, it goes to the database and do a "select max(id) ..." and cache the result in a variable (call it "next"). With every subsequent request, the IncrementGenerator increments "next" and returns it -- this is synchronized, so I would think multi-threading is not an issue -- but don't believe me; do your own testing if you want to be sure.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 27, 2008 10:55 pm 
Regular
Regular

Joined: Wed Jun 21, 2006 3:13 pm
Posts: 110
schauder wrote:
generates identifiers of type long, short or int that are unique only when no other process is inserting data


And, as it was, his id was unique only when no other process was inserting data.


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.