Reputation: 2423
I am developing an application for a medical channelling centre where multiple users reserve bookings for doctors with JSF and JPA. A sequence number is unique to the Doctor, Date and Session. I tried to get a unique sequence number from counting the previous bookings and add one, but if two requests comes at the same time, two bookings get the same number causing trouble to functionality. How can I get unique number in this case? Can I use an application wide bean to generate it? (I thought it is not practicle to get the unique number from the database sequence number as there are several doctors, sessions and daily they have to have different booking number.)
Upvotes: 0
Views: 360
Reputation: 14363
This is a perfect case for using a sequence in Database.
You should created ID in your DB table and make sure that the field is auto generated by means of a sequence and then you need not to bother that the same value is used for two rows.
Upvotes: 0
Reputation: 691655
Here's how I would do it:
Have a table with 6 columns in the database:
@Version
, for optimistic locking)Make sure to add a unique contraint on [doctorId, date, session].
Create a service, running in its own transaction (REQUIRES_NEW propagation), called
getNextValue(doctorId, date, session)
This service should get the counter corresponfing to its three arguments from the database table, return it, and increment it. If there is no row yet, it should create it.
There's still a possibility to have two concurrent transactions try to create or increment the same row concurrently. In the case of a creation, one of the transactions would rollback due to the unique contraint. In the case of an increment, one of the transactions would rollback due to the JPA optimistic locking.
If the service rolls back, then retry it, until there is no exception anymore.
This avoids storing all these counters in memory, is stateless and thus doesn't cause any problem if you restart your application, and works even if you have a cluster of servers.
Upvotes: 1