Ensuring unique serial numbers in a Hibernate session
I am writing a system that holds a hibernate-managed entity called Voucher that has a field named serialNumber, which holds a unique number for the only-existing valid copy of the voucher instance. There may be old, invalid copies in the database table as well, which means that the database field may not be declared unique. The operation that saves a new valid voucher instance (that will need a new serial number) is, first of all, synchronized on an appropriate entity. Thereafter the whole procedure is encapsulated in a transaction, the new value is fetched by the JPQL SELECT MAX(serialNumber) + 1 FROM Voucher the field gets the result from the query, the instance is thereafter saved, the session is flushed, the transaction is committed and the code finally leaves the synchronized block. In spite of all this, the database sometimes (if seldom) ends up with Vouchers with duplicate serial numbers. My question is: Considering that I am rather confident in the synchronization and transaction handling, is there anything more or less obvious that I should know about hibernate that I have missed, or should I go back to yet another debugging session, trying to find anything else causing the problem? The service running the save process is a web application running on tomcat6 and is managed by Spring's HttpRequestHandlerServlet. The db connections are pooled by C3P0, running a very much default-based configuration. I'd appreciate any suggestion Thanks
You can use a MultipleHiLoPerTableGenerator: it generate #Id outside current transaction.
You do not need to debug to find the cause. In a multi-threaded environment it is likely to happen. You are selecting max from your table. So suppose that TX1 reads the max value which is a and inserts a row with serial number a+1; at this stage if any TX2 reads DB, the max value is still a as TX1 has not committed its data. So TX2 may insert a row with serial number of a+1 as well. To avoid this issue you might decide to change Isolation Level of your database or change the way you are getting serial numbers (it entirely depends on circumstances of your project). But generally I do not recommend changing Isolation Levels as it is too much effort for such an issue.
How to update changes in tomcat without restarting while site is live?
Java/Chess Odd Gui Bug
Android store file size in long variable
What's a good way to display text messages in JavaFX FXML?
Running this from command line in Java
Insert a string variable inside a Where Clause
close() is not working, everytime a new window gets open
Upload multiple image to Parse Server Android Java
How to execute with Jooq arbitrary number of selects joined with UNION
How to get time difference between two ZonedDateTimes and pretty print it like “4 hours, 1 minute, 40 seconds ago”?
Log4J : Cannot create file using environment variable
How to use classloader to load class file from server to client
JUnit and multithreading: how to run another thread with data generation inside JUnit test of Spring Boot App?
How to add CSV file to MySQL database with the help of SQL commands and Java?
json array/object iteration in java android
Android: Cannot call Java Web Service through App