I have a java servlet which interacts with hibernate . It is necessary to generate a check id on the system thus:
for (long j = 0; j < soldProductQuantity.longValue(); j++) {
checkId = Hotel.getNextMcsCheckAndIncrement();
checkIdString = checkId.toString();
McsCheck.generateCheck(checkIdString);
}
where getNextMcsCheckAndIncrement()
is defined as
static public synchronized Long getNextMcsCheckAndIncrement()
It pulls a value from the database using hibernate, does some operations on it, stores the modified value back, then returns the number.
Because getNextMcsCheckAndIncrement
is synchronized, I would expect no two checks to have the same number, because no two threads could enter that method at the same time.
Yet I can see in my data repeated instances of multiple check ids. So clearly this isn't working. What am I missing?
The implementation of getNext as asked:
// Increment FIRST, then return the resulting value as the current MCS check value.
static public synchronized Long getNextMcsCheckAndIncrement() {
Hotel theHotel = null;
Long checkCounter;
@SuppressWarnings("unchecked")
List<Hotel> hotelList = Hotel.returnAllObjects();
for (Hotel currentHotel : hotelList) { // there should be only one.
theHotel = currentHotel;
}
checkCounter = theHotel.getMcsCheckCounter()+1;
theHotel.setMcsCheckCounter(checkCounter);
theHotel.update();
return checkCounter;
}
static public List returnAllObjects() {
return Hotel.query ("from Hotel");
}
static public List query(String queryString) {
Session session = HibernateUtil.getSessionFactory().openSession();
List result = session.createQuery(queryString).list();
session.close();
return result;
}
public void update() {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.update(this);
transaction.commit();
session.close();
}
Yes, I know it's not the best way to do it, and I'll solve that in time. But the immediate issue is why concurrency fails.