-->
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: garantuee unique invoice numbers with hibernate?
PostPosted: Wed Oct 12, 2005 9:04 am 
Newbie

Joined: Mon Jan 17, 2005 1:09 pm
Posts: 19
Hibernate 3
Mysql

The following code can be executed simultaneously.Is there a way to garanty that the invoice number will allways be unique?
I was trying to do this with with lockmodes, but I couldn't find a way to lock the "max(inv.nr)" result.
When I execute this code simultaneous, I end up whith non unique invoice numbers.


Code:
public static void saveInvoices(List invoices){
   Session hibSession = sessionFactory.openSession();
   Transaction tx = hibSession.beginTransaction();
   try{
       Query q = hibSession.createQuery("select max(inv.number) from Invoice as inv");           
       //doens't work (gives an error :invalid alias "inv")
       //q.setLockMode("inv",LockMode.UPGRADE);
       //
       Long lastInvoiceNumber = (Long)q.uniqueResult();

       Long newInvoiceNumber = lastInvoiceNumber + 1L;
       for(Iterator <Invoice>it=invoices.iterator();it.hasNext();){
          Invoice invoice2save = it.next();
          invoice2save.setNumber(newInvoiceNumber);
        
          hibSession.saveOrUpdate(invoice2save);

          newInvoiceNumber++;      
       }
      
       tx.commit();
   }catch (HibernateException he) {
       tx.rollback();
       throw he;
   }finally {
       hibSession.close();
   }   


All sugestions are welcome


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 9:18 am 
Senior
Senior

Joined: Thu Aug 04, 2005 4:54 am
Posts: 153
Location: Birmingham, UK
Set the invoice number property to be unique in the database and when a duplicated invoice is saved an exception will be thrown.

That seems the simplest way to solve it. Of course you can quite easilly criticse it by pointing out that an exception should be exceptional and is not a part of business logic.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 10:30 am 
Newbie

Joined: Mon Jan 17, 2005 1:09 pm
Posts: 19
this solution would indeed keep the database consistent, but would cause an ungly exceptions to the user. The change that this exception occurs is really small. If somebody has an more ellegant solution (with DB locks?), I would appriciate to hear it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 11:16 am 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
why don't you just have the db generate the invoice numbers using a sequence generator instead of doing it in the code.

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 11:34 am 
Newbie

Joined: Mon Jan 17, 2005 1:09 pm
Posts: 19
I want to be in control of my invoice numbers and the invoice number shouldn't be the primary key of my invoice table.

I should lock the entire invoices tables during the scope of the method.
I don't think there is as way to do this via Hibernate. I will try to do this with handcoded sql: " LOCK TABLES `Invoice` WRITE;"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 5:43 pm 
Newbie

Joined: Sun Sep 21, 2003 3:04 pm
Posts: 11
Location: Germany
hi heox,

have the same problem here,
can you give me some hints.

Heox wrote:
I want to be in control of my invoice numbers and the invoice number shouldn't be the primary key of my invoice table.

I should lock the entire invoices tables during the scope of the method.
I don't think there is as way to do this via Hibernate. I will try to do this with handcoded sql: " LOCK TABLES `Invoice` WRITE;"

_________________
_______________________
With best regards
S.Homburg
21220 Seevetal / GERMANY


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 6:31 pm 
Beginner
Beginner

Joined: Sat Oct 22, 2005 11:16 pm
Posts: 40
Do you want users to be able to supply an invoice number? If that is the case, you'll need to start your transaction, check to see if the invoice number is already in use, and if it is, return a nice error message to the user.

Or, do you want to use auto-generated invoice numbers, but you want them to be of a particular form, so you don't start with Invoice #1 and go up from there? If that's the case, what I would do is use an integer identifier, generated by the increment or native generators, and then use some one-to-one formula to display to to the user. For example, if you have a sequence number called "id" you could say:

invoiceNumber = id * 7 + 1001;

That way it will sort of obscure exactly which invoice number you are looking at, and if some user somewhere supplies an invoice number, you can do a pre-check to see if it could even possibly be a valid one.

This kind of thing is done all the time. That's how credit card numbers work. Some of the digits indicate the credit card family (Visa, MC, etc). Some indicate the specific issuing bank. And then there is a checksum formula for the whole thing. Presumably the issuing bank has a plain old sequence number, and then some kind of transformation to use to generate the final CC number.

Does this help?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 6:33 pm 
Beginner
Beginner

Joined: Sat Oct 22, 2005 11:16 pm
Posts: 40
By the way, I would definitely recommend that you NOT let users pick their own invoice numbers out of their imagination. That just doesn't make sense from a usability standpoint.

And of course, in my formula above, to go from the invoice number back to the id, you use:

id = (invoiceNumber - 1001) / 7

with appropriate checks to make sure that the invoice number supplied was a valid one and the result is an integer.


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.